First, i'm not sure if i'm formulating the question correctly. So I have a bash script that delete a user in a system. The problem is, it is showing the err msg before the terminal code. Here. Code:
echo -e "\nCommencing user $UserName removal"
echo -e "Deactivating $UserName shell account ..." "$(chsh -s /usr/bin/false $UserName)"
echo -e "Listing group(s) user: " "$(groups $UserName)"
echo -e "Removing Crontab ... " "$(crontab -r -u $UserName)"
Here is the output:
Commencing user Test2 removal
chsh: unknown user: Test2
Deactivating Test2 shell account ...
groups: Test2: no such user
Listing group(s) user:
scripts/sudo.sh: line 332: /delete_Test2/crontab.bak: No such file or directory
Saving Crontab ...
The user to delete is Test2, which is this case "supposedly" does not exist (a different question for a different time). Now, shouldn't the stderr msg display next to the command or below it instead of above it?
Thanks in advance
When the shell executes the line
echo -e "Deactivating $UserName shell account ..." "$(chsh -s /usr/bin/false $UserName)"
, here's the sequence of events:chsh -s /usr/bin/false Test2
, with its stdout going to a capture buffer so the shell can use it later.chsh
discover's that "Test2" doesn't exist, and prints "chsh: unknown user: Test2" to its stderr. Since the shell didn't do anything special with its stderr, this goes directly to the shell's stderr, which is your terminal.chsh
exitschsh
(there wasn't any), and substitutes it into theecho
command line, givingecho -e "Deactivating Test2 shell account ..." ""
Note that the error message gets printed at step 2, but the message about what's supposedly about to happen doesn't get printed until step 4.
There are several ways to solve this; generally the best is to avoid the whole mess of capturing the command's output, then echoing it. It's pointless, and just leads to confusions like this (and some others you haven't run into). Just run the command directly, and let its output (both stdout and stderr) go to their normal places, in normal order.
BTW, I also recommend avoiding
echo -e
, or indeedecho -anything
. The POSIX standard forecho
says "Implementations shall not support any options." In fact, some implementations do support options; others just treat them as part of the string to be printed. Also, some interpret escape sequences (like\n
) in the strings to print, some don't, and some only do if-e
is specified (violating the POSIX standard). Given how unpredictable these features are, it's best to just avoid such iffy situations, and either useprintf
instead (which is more complicated to use, but much more predictable), or (as in your case) just use a separateecho
command for each line.Also, you should almost always double-quote variable references (e.g.
groups "$UserName"
instead ofgroups $UserName
), just in case they contain spaces, wildcards, etc.Based on the above, here's how I'd write the script: