LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Distributions > CentOS
User Name
Password
CentOS This forum is for the discussion of CentOS Linux. Note: This forum does not have any official participation.

Notices


Reply
  Search this Thread
Old 10-13-2022, 08:03 PM   #1
Aragorn7233
LQ Newbie
 
Registered: Oct 2022
Posts: 3

Rep: Reputation: 0
Inconsistent tr Command Utility Results


Environment:
CentOS Linux release 7.9.2009 (Core)
tr (GNU coreutils) 8.22

Problem Description:

The tr command utility is used in several of our scripts and it has worked without issue for several years and is currently working in the "primary" production site. During our business continuity exercise we migrate our processing to an alternate site. During the period of the exercise, errors were encountered with the scripts that utilize the tr utility command. The errors were caused by the tr utility failing to translate the characters in a variable from uppercase to lowercase.

Further investigation revealed that the tr command worked within a script correctly in the alternate site if executed from the command line but failed if invoked from the cron service or other service utility.

The example below contains the script that was used to verify this condition along with the debug log from an execution via the command line and the execution results from a crontab service call. The results show the tr command translation of the "CLIENT" variable from uppercase to lowercase. The command line execution is successful while the crontab entry attempt shows "tr y y" in the debug output.

This condition does not exist in primary site and both sites are running the same version of CentOS as well as the same versions of the tr utility.

***** Test Script ******
#!/bin/bash
set -x
numParms=$#
if [ ${numParms} -ge 2 ] ; then
ENV=`echo ${2} | tr [A-Z] [a-z]`
fi
CLIENT=${1}
CLIENT_LC=`echo ${CLIENT} | tr [A-Z] [a-z]`
echo "Input parameter 1 [${1}] : Environment variable [${ENV}]"
if [ "${ENV}" == "tst" ]; then
echo "Test environment variable detected"
elif [ "${ENV}" == "prd" ]; then
echo "Production environment variable detected"
else
echo "Invalid environment parameter passed: ${ENV}"
fi
echo "Client Name [${CLIENT}] Lowercase Client Name [${CLIENT_LC}]"


***** Executed Via Command Line ******
./tr-testing.sh CHECK-INFO tst
+ numParms=2
+ '[' 2 -ge 2 ']'
++ echo tst
++ tr '[A-Z]' '[a-z]'
+ ENV=tst
+ CLIENT=CHECK-INFO
++ echo CHECK-INFO
++ tr '[A-Z]' '[a-z]'
+ CLIENT_LC=check-info
+ echo 'Input parameter 1 [CHECK-INFO] : Environment variable [tst]'
Input parameter 1 [CHECK-INFO] : Environment variable [tst]
+ '[' tst == tst ']'
+ echo 'Test environment variable detected'
Test environment variable detected
+ echo 'Client Name [CHECK-INFO] Lowercase Client Name [check-info]'
Client Name [CHECK-INFO] Lowercase Client Name [check-info]


***** Executed Via Crontab ******
/my/home/work/drt2022-6/tr-testing.sh CHECK-INFO tst > /home/gerald.cata/work/drt2022-6/test-info-20221011.log 2<&1
+ numParms=2
+ '[' 2 -ge 2 ']'
++ echo tst
++ tr y y
+ ENV=tst
+ CLIENT=CHECK-INFO
++ echo CHECK-INFO
++ tr y y
+ CLIENT_LC=CHECK-INFO
+ echo 'Input parameter 1 [CHECK-INFO] : Environment variable [tst]'
Input parameter 1 [CHECK-INFO] : Environment variable [tst]
+ '[' tst == tst ']'
+ echo 'Test environment variable detected'
Test environment variable detected
+ echo 'Client Name [CHECK-INFO] Lowercase Client Name [CHECK-INFO]'
Client Name [CHECK-INFO] Lowercase Client Name [CHECK-INFO]
 
Old 10-13-2022, 09:54 PM   #2
wpeckham
LQ Guru
 
Registered: Apr 2010
Location: Continental USA
Distribution: Debian, Ubuntu, RedHat, DSL, Puppy, CentOS, Knoppix, Mint-DE, Sparky, VSIDO, tinycore, Q4OS,Manjaro
Posts: 5,623

Rep: Reputation: 2695Reputation: 2695Reputation: 2695Reputation: 2695Reputation: 2695Reputation: 2695Reputation: 2695Reputation: 2695Reputation: 2695Reputation: 2695Reputation: 2695
Options are A. find out why "tr" is not behaving correctly. B. eliminate the use of "tr".

A. There are several things I would check to troubleshoot the behavior, but I would start with examining these things:
#1 the environment as set under CRON. Since you have not set environment variable directly in the script, it is possible that there are differences that pertain. LANG is one example of a variable of interest.

#2 I would check for "tr" executibles and ensure that there is only one, or that the specific one desired is the only one addressed by the script no matter how called. Setting PATH in the script is one way, but calling external applications using the full path is another.

B. since you are using bash as the script, and all you are doing is changing case, why call "tr". Bash string handling can handle this without an external call for more reliable behavior (although LANG still needs to be set properly) with fewer cycles and fewer IO operations. It is lightly covered in the bash man pages, but there are MANY web pages with additional examples. See https://linuxhandbook.com/bash-strings/ for one.
 
Old 10-13-2022, 10:18 PM   #3
michaelk
Moderator
 
Registered: Aug 2002
Posts: 25,700

Rep: Reputation: 5895Reputation: 5895Reputation: 5895Reputation: 5895Reputation: 5895Reputation: 5895Reputation: 5895Reputation: 5895Reputation: 5895Reputation: 5895Reputation: 5895
Code:
+ numParms=2
+ '[' 2 -ge 2 ']'
++ echo TST
++ tr '[A-Z]' '[a-z]'
+ ENV=tst
+ CLIENT=TEST
++ echo TEST
++ tr '[A-Z]' '[a-z]'
+ CLIENT_LC=test
+ echo 'Input parameter 1 [TEST] : Environment variable [tst]'
Input parameter 1 [TEST] : Environment variable [tst]
+ '[' tst == tst ']'
+ echo 'Test environment variable detected'
Test environment variable detected
+ echo 'Client Name [TEST] Lowercase Client Name [test]'
Client Name [TEST] Lowercase Client Name [test]
On my CentOS 7 it works as expected via cron.

Are you sure the script running via cron is identical to what is posted?

I do not know why your output is different nor why you are seeing
tr y y versus tr '[A-Z]' '[a-z]'

Last edited by michaelk; 10-14-2022 at 09:07 AM.
 
Old 10-14-2022, 02:45 AM   #4
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,838

Rep: Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308
It looks like: tr [A-Z] [a-z] is replaced (tr y y). That means you have a file named y in the directory where this script was executed (or something similar). You need to use shellcheck to check your script and to avoid situations like this.
In general you must use quotation, like: tr '[A-Z]' '[a-z]'. But as it was mentioned you can replace this tr in your case with a more efficient solution.

Additionally you would need to use code tags.

Last edited by pan64; 10-14-2022 at 02:46 AM.
 
Old 10-14-2022, 09:58 AM   #5
Aragorn7233
LQ Newbie
 
Registered: Oct 2022
Posts: 3

Original Poster
Rep: Reputation: 0
Inconsistent tr Command Utility Results

As I noted in my initial submission; the tr command is working fine in the primary production environment from all other service calls including cron. The variable being translated is being passed as a parameter to the script so there aren't any directory files involved in the issue. I understand that there are alternatives to the use of the tr command but that does not provide the an answer for why the inconsistent execution between invoking the command via a service call and invoking it via the command line.

I already exhausted the usual suspects such as whether there were other instances of the tr command residing elsewhere.

The one item the was suggested regarding the environment setting for cron, I have not investigated and will look into that.

Thank you for your responses.
 
Old 10-14-2022, 10:17 AM   #6
boughtonp
Senior Member
 
Registered: Feb 2007
Location: UK
Distribution: Debian
Posts: 3,599

Rep: Reputation: 2546Reputation: 2546Reputation: 2546Reputation: 2546Reputation: 2546Reputation: 2546Reputation: 2546Reputation: 2546Reputation: 2546Reputation: 2546Reputation: 2546

1. Read man tr more carefully.
2. Pay more attention to the debug output you are receiving.

The tr command is consistently doing what it is told in all situations, but since you have unquoted shell metacharacters, tr is receiving different arguments from the shell when in a directory where those metacharacters become relevant. i.e. If your command uses brackets, you MUST quote/escape them to prevent shell interpretation, but the syntax you are using is incorrect and that it works is a coincidence.

You want either "tr A-Z a-z" or "tr '[:upper:]' '[:lower:]'"

Use ShellCheck to identify other issues which may occur.

 
Old 10-14-2022, 05:17 PM   #7
Aragorn7233
LQ Newbie
 
Registered: Oct 2022
Posts: 3

Original Poster
Rep: Reputation: 0
Inconsistent tr Command Utility Results

It appears that the parameters, as passed during the cronjob on this particular server, do need to be individually quoted. I ran the command directly from a crontab entry and, lo and behold, the tr command complained when the parameters passed were not quoted and was successful after adding the quotes to the parameters to the tr command.

/usr/bin/echo CHECK-INFO | /usr/bin/tr [A-Z] [a-z] result: CHECK-INFO (Did not work)

/usr/bin/echo CHECK-INFO | /usr/bin/tr "[A-Z]" "[a-z]" result: check-info (Worked as desired)

I also updated my test script and added the quotes around the tr parameters and it also worked. So, the mystery is solved even though on the primary production server the issue is not present.

Thank you all for providing feedback. It did provide me some alternative avenues to explore.
 
Old 10-15-2022, 01:33 AM   #8
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,838

Rep: Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308
Quote:
Originally Posted by Aragorn7233 View Post
It appears that the parameters, as passed during the cronjob on this particular server, do need to be individually quoted.
This statement is wrong. When unquoted the shell will try to evaluate it before execution, so the result will depend on that evaluation.
You can check it if you execute set -xv before those thest commands:
Code:
$ set -xv
$ /usr/bin/echo CHECK-INFO | /usr/bin/tr [A-Z] [a-z]
/usr/bin/echo CHECK-INFO | /usr/bin/tr [A-Z] [a-z]
+ /usr/bin/echo CHECK-INFO
+ /usr/bin/tr '[A-Z]' '[a-z]'
check-info
$ touch q
touch q
+ touch q
$ /usr/bin/echo CHECK-INFO | /usr/bin/tr [A-Z] [a-z]
/usr/bin/echo CHECK-INFO | /usr/bin/tr [A-Z] [a-z]
+ /usr/bin/echo CHECK-INFO
+ /usr/bin/tr '[A-Z]' q
qqqqq-qqqq
$ touch P
touch P
+ touch P
$ /usr/bin/echo CHECK-INFO | /usr/bin/tr [A-Z] [a-z]
/usr/bin/echo CHECK-INFO | /usr/bin/tr [A-Z] [a-z]
+ /usr/bin/echo CHECK-INFO
+ /usr/bin/tr P q
CHECK-INFO
Explanation: you can see the evaluated commands one by one after the + sign (before execution)
 
Old 10-15-2022, 10:20 AM   #9
wpeckham
LQ Guru
 
Registered: Apr 2010
Location: Continental USA
Distribution: Debian, Ubuntu, RedHat, DSL, Puppy, CentOS, Knoppix, Mint-DE, Sparky, VSIDO, tinycore, Q4OS,Manjaro
Posts: 5,623

Rep: Reputation: 2695Reputation: 2695Reputation: 2695Reputation: 2695Reputation: 2695Reputation: 2695Reputation: 2695Reputation: 2695Reputation: 2695Reputation: 2695Reputation: 2695
Using the bash shell internals in referenced (linked) in #2, you avoid interpretation of parameters that could detect external objects during the execution. By working directly and only upon the strings already in the environment using only the internal tools you avoid not only the external call, but also any chance of that interpretation addressing outside the script for that operation. This makes the script more robust, more correct, and generally faster.

Of course, one COULD recode the entire thing in PERL or another more powerful tool than the shell to obtain similar advantage, but when you already have a solution in bash that only needs the use of tr corrected that seems ill advised. Just using modern bash properly should suffice to solve the immediate issue, and avoid any future issues that might results from vulnerable tr calls, tr behavior, or tr behavior changes.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Inconsistent results using ping, dig, nslookup, whois, host steelaz Linux - Networking 3 04-05-2009 07:50 AM
CD drive problem? - inconsistent media check results liquorvicar Linux - Hardware 0 10-11-2007 06:00 AM
inconsistent results from modprobe nyloc Slackware 4 08-09-2007 08:40 PM
Analyzing disk usage: inconsistent results from du, df overbored Linux - Software 3 12-01-2006 09:23 PM
php array sort inconsistent results rblampain Programming 2 04-03-2006 12:34 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Distributions > CentOS

All times are GMT -5. The time now is 01:20 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration