log the exit code of a script after it completes[SOLVED]

About writing shell scripts and making the most of your shell
Forum rules
Topics in this forum are automatically closed 6 months after creation.
Locked
chowse
Level 2
Level 2
Posts: 87
Joined: Sun May 14, 2017 10:02 am

log the exit code of a script after it completes[SOLVED]

Post by chowse »

Hello && Merry Christmas && Happy New Year!

I will run this script from crontab.

Code: Select all

#!/bin/sh

## REQUIRES 'sudo' or run from crontab

# Exit on errors?
set -e

#Start with an empty backup.txt file
[ -f /home/charles/backup.txt ] && rm /home/charles/backup.txt || touch /home/charles/backup.txt

date >> /home/charles/backup.txt
echo >> /home/charles/backup.txt

# Sync the Primary and Backup discs
echo "Beginning backups" >> /home/charles/backup.txt

rsync -au --delete --ignore-errors /media/charles/Primary/* /media/charles/Backup
    
echo >> /home/charles/backup.txt

# Backup the /home directory
rsync -au --delete --ignore-errors /home/ /media/charles/Laptop/home 

cd /media/charles/Laptop/home 

# Remove hidden directories, but save hidden files
find -type d -name '.*' -and -not -name '.' -print0 | xargs -0 rm -rf 

# Make backup.txt belong to charles
chown charles /home/charles/backup.txt

# Make Laptop/home belong to charles
chown charles /media/charles/Laptop/home

echo -n "Backups completed at " >> /home/charles/backup.txt; date >> /home/charles/backup.txt

echo >> /home/charles/backup.txt

exit

I propose this command for crontab: bakup.sh && echo "Exited with status of" $? >> backup.txt

That gives me the desired result for my 'log' file, but how should I test for error reporting?
i.e. what should I bork to generate an error for testing purposes?

TIA,
Charles
Last edited by LockBot on Wed Dec 28, 2022 7:16 am, edited 2 times in total.
Reason: Topic automatically closed 6 months after creation. New replies are no longer allowed.
Some people make happiness wherever they go, others whenever they go.
User avatar
xenopeek
Level 25
Level 25
Posts: 29459
Joined: Wed Jul 06, 2011 3:58 am

Re: log the exit code of a script after it completes

Post by xenopeek »

Changing either the username or the path to one that doesn't exist should have chown return exit code 1.
chown charles /home/charles/backup.txt
Image
chowse
Level 2
Level 2
Posts: 87
Joined: Sun May 14, 2017 10:02 am

Re: log the exit code of a script after it completes

Post by chowse »

xenopeek wrote:Changing either the username or the path to one that doesn't exist should have chown return exit code 1.
chown charles /home/charles/backup.txt
Thanks for the reply.
That did indeed cause the script to exit with 1, but it did not write to backup.txt...

charles@MOE ~ $ sudo ./bakup.sh && echo >> backup.txt && echo "Exited with status of" $? >> backup.txt
chown: invalid user: ‘bob’
charles@MOE ~ $ echo $?
1
backup.txt says...
................
Tue Dec 26 13:42:48 CST 2017
Beginning backups
................

While I was expecting...
................
Tue Dec 26 13:42:48 CST 2017
Beginning backups
Exited with status of 1
................
Some people make happiness wherever they go, others whenever they go.
User avatar
xenopeek
Level 25
Level 25
Posts: 29459
Joined: Wed Jul 06, 2011 3:58 am

Re: log the exit code of a script after it completes

Post by xenopeek »

sudo ./bakup.sh && echo >> backup.txt && echo "Exited with status of" $? >> backup.txt
&& means execute the next command if and only if the previous command was successful. So if sudo ./bakup.sh fails the rest of the command line is not executed. To run one command after another, regardless of the previous commands' exit code, separate them with ; instead of &&.
Image
FreedomTruth
Level 4
Level 4
Posts: 443
Joined: Fri Sep 23, 2016 10:19 am

Re: log the exit code of a script after it completes

Post by FreedomTruth »

Also, simply replacing && with ; will not do what you might expect: sudo ./bakup.sh ; echo >> backup.txt ; echo "Exited with status of" $? >> backup.txt should always report an exit status of 0.
Why? Break it down ...
(1) sudo .bakup.sh -- returns error 1 for example
(2) echo >> backup.txt -- now returns error 0
(3) echo "Exited with status of" $? >> backup.txt will report the 0 exit status from the previous echo command.

What may work better is sudo ./bakup.sh ; echo -e "\nExited with status of "$? >> backup.txt
chowse
Level 2
Level 2
Posts: 87
Joined: Sun May 14, 2017 10:02 am

Re: log the exit code of a script after it completes

Post by chowse »

FreedomTruth wrote:Also, simply replacing && with ; will not do what you might expect: sudo ./bakup.sh ; echo >> backup.txt ; echo "Exited with status of" $? >> backup.txt should always report an exit status of 0.
Why? Break it down ...
(1) sudo .bakup.sh -- returns error 1 for example
(2) echo >> backup.txt -- now returns error 0
(3) echo "Exited with status of" $? >> backup.txt will report the 0 exit status from the previous echo command.

What may work better is sudo ./bakup.sh ; echo -e "\nExited with status of "$? >> backup.txt
Hi, thanks for the reply. I changed 'charles' to 'bob' in one of the chown lines...

terminal...
charles@MOE ~ $ sudo ./bakup.sh ; echo -e "\nExited with status of "$? >> backup.txt
chown: invalid user: ‘bob’
bash: backup.txt: Permission denied

backup.txt...
Tue Dec 26 16:01:02 CST 2017

Beginning backups

Backups completed at Tue Dec 26 16:04:21 CST 2017

There's no exit status report...??
Some people make happiness wherever they go, others whenever they go.
FreedomTruth
Level 4
Level 4
Posts: 443
Joined: Fri Sep 23, 2016 10:19 am

Re: log the exit code of a script after it completes

Post by FreedomTruth »

Ah, we have a permission issue at hand. root owns "backup.txt" at this point; the bakup.sh has finished, so our unprivileged user cannot append to the file.
One ugly way around this is to sudo the echo command too: sudo ./bakup.sh ; sudo bash -c "echo -e \"\nExited with status of \"$? >> backup.txt"
chowse
Level 2
Level 2
Posts: 87
Joined: Sun May 14, 2017 10:02 am

Re: log the exit code of a script after it completes

Post by chowse »

FreedomTruth wrote:Ah, we have a permission issue at hand. root owns "backup.txt" at this point; the bakup.sh has finished, so our unprivileged user cannot append to the file.
One ugly way around this is to sudo the echo command too: sudo ./bakup.sh ; sudo bash -c "echo -e \"\nExited with status of \"$? >> backup.txt"
Whew...
terminal...
charles@MOE ~ $ sudo ./bakup.sh ; sudo bash -c "echo -e \"\nExited with status of \"$? >> backup.txt"
[sudo] password for charles:
chown: invalid user: ‘bob’

backup.txt...
Tue Dec 26 16:25:28 CST 2017

Beginning backups

Backups completed at Tue Dec 26 16:28:56 CST 2017

Exited with status of 0


If you're getting frustrated with me, I apologize.
I'd be happy to discuss any changes to the script that would let me catch errors and log them to backup.txt.
Some people make happiness wherever they go, others whenever they go.
FreedomTruth
Level 4
Level 4
Posts: 443
Joined: Fri Sep 23, 2016 10:19 am

Re: log the exit code of a script after it completes

Post by FreedomTruth »

Maybe this is something your shell is doing differently ... try changing the first line in the script to: #!/bin/bash and see if it works as expected then? Personally I'm unfamiliar with that set -e which isn't even mentioned in my old reference book. From your output file, it seems to not have stopped the script at the error, and continued, thinking it completed.
chowse wrote:I'd be happy to discuss any changes to the script that would let me catch errors and log them to backup.txt.
Error handling is probably better done within the script itself, so you can tell exactly where it failed. Something like this? (not tested -- if it's buggy and you need more help I can try again)

Code: Select all

#!/bin/bash

## REQUIRES 'sudo' or run from crontab
if [ $UID -ne 0 ]; then
  echo ERROR: Restart this script with sudo, or run from crontab.
  exit 1
fi

#Start with an empty backup.txt file
[ -f /home/charles/backup.txt ] && rm /home/charles/backup.txt || touch /home/charles/backup.txt

date >> /home/charles/backup.txt
echo >> /home/charles/backup.txt

# Sync the Primary and Backup discs
echo "Beginning backups" >> /home/charles/backup.txt

rsync -au --delete --ignore-errors /media/charles/Primary/* /media/charles/Backup
lasterr=$?
if [ $lasterr -ne 0]; then
  echo "rsync error $lasterr while backing up Primary" >> /home/charles/backup.txt
  exit $lasterr
fi
   
echo >> /home/charles/backup.txt

# Backup the /home directory
rsync -au --delete --ignore-errors /home/ /media/charles/Laptop/home
lasterr=$?
if [ $lasterr -ne 0 ]; then
  echo "rsync error $lasterr while backing up home" >> /home/charles/backup.txt
  exit $lasterr
fi

cd /media/charles/Laptop/home

# Remove hidden directories, but save hidden files
find -type d -name '.*' -and -not -name '.' -print0 | xargs -0 rm -rf

# Make backup.txt belong to charles
chown charles /home/charles/backup.txt
lasterr=$?
if [ $lasterr -ne 0 ]; then
  echo "chown error $lasterr on file backup.txt" >> /home/charles/backup.txt
  exit $lasterr
fi

# Make Laptop/home belong to charles
chown charles /media/charles/Laptop/home
lasterr=$?
if [ $lasterr -ne 0 ]; then
  echo "chown error $lasterr on directory /media/charles/Laptop/home" >> /home/charles/backup.txt
  exit $lasterr
fi

echo -n "Backups completed at " >> /home/charles/backup.txt; date >> /home/charles/backup.txt

echo >> /home/charles/backup.txt

exit 0
chowse
Level 2
Level 2
Posts: 87
Joined: Sun May 14, 2017 10:02 am

Re: log the exit code of a script after it completes

Post by chowse »

[quote="FreedomTruth"] (not tested -- if it's buggy and you need more help I can try again)

Code: Select all


This looks good!  
Your script did exit with status 1 after I changed the chown to bob instead of charles!!

May I add you as a Friend?
Thank you kindly!
Charles
Some people make happiness wherever they go, others whenever they go.
FreedomTruth
Level 4
Level 4
Posts: 443
Joined: Fri Sep 23, 2016 10:19 am

Re: log the exit code of a script after it completes

Post by FreedomTruth »

Sorry, looks like I missed a space there. Change line 20 from if [ $lasterr -ne 0]; then to if [ $lasterr -ne 0 ]; then (put a space after the 0 before the closing bracket).
chowse
Level 2
Level 2
Posts: 87
Joined: Sun May 14, 2017 10:02 am

Re: log the exit code of a script after it completes

Post by chowse »

FreedomTruth wrote:Sorry, looks like I missed a space there. Change line 20 from if [ $lasterr -ne 0]; then to if [ $lasterr -ne 0 ]; then (put a space after the 0 before the closing bracket).
You may be looking at my post before I edited it. I found the missing space and corrected it. Script works great!

Thank you kindly!
May I add you as a Friend?
Some people make happiness wherever they go, others whenever they go.
FreedomTruth
Level 4
Level 4
Posts: 443
Joined: Fri Sep 23, 2016 10:19 am

Re: log the exit code of a script after it completes

Post by FreedomTruth »

chowse wrote:May I add you as a Friend?
Fine by me ... not sure what that does in this forum though :)
Also, if anyone cares to explain what set -e does in his initial script, I'd like to find that out too. Apparently it's supposed to stop the script when it encounters an error, but does not return a non-zero exit code?
User avatar
xenopeek
Level 25
Level 25
Posts: 29459
Joined: Wed Jul 06, 2011 3:58 am

Re: log the exit code of a script after it completes[SOLVED]

Post by xenopeek »

FreedomTruth wrote:Also, if anyone cares to explain what set -e does in his initial script, I'd like to find that out too. Apparently it's supposed to stop the script when it encounters an error, but does not return a non-zero exit code?
That's covered in the bash manpage, SHELL BUILTINS section. For set -e it says:

Code: Select all

Exit  immediately  if  a pipeline (which may consist of a single simple command), a list, or a compound command (see
SHELL GRAMMAR above), exits with a non-zero status.  The shell does not exit if the command that fails  is  part  of
the  command list immediately following a while or until keyword, part of the test following the if or elif reserved
words, part of any command executed in a && or || list except the command following the final && or ||, any  command
in  a pipeline but the last, or if the command's return value is being inverted with !.  If a compound command other
than a subshell returns a non-zero status because a command failed while -e was being ignored, the  shell  does  not
exit.   A trap on ERR, if set, is executed before the shell exits.  This option applies to the shell environment and
each subshell environment separately (see COMMAND EXECUTION ENVIRONMENT above), and  may  cause  subshells  to  exit
before executing all the commands in the subshell.

If  a  compound command or shell function executes in a context where -e is being ignored, none of the commands exe‐
cuted within the compound command or function body will be affected by the -e setting, even if -e is set and a  com‐
mand  returns  a failure status.  If a compound command or shell function sets -e while executing in a context where
-e is ignored, that setting will not have any effect until the compound command or the command containing the  func‐
tion call completes.
Image
FreedomTruth
Level 4
Level 4
Posts: 443
Joined: Fri Sep 23, 2016 10:19 am

Re: log the exit code of a script after it completes[SOLVED]

Post by FreedomTruth »

Thanks for the explanation (or, at least, copying and pasting it) :)
man bash takes forever to find that, even with searching "BUILTIN" then searching "set"

I see, I was doing it wrong. search for "set \[" and it's the 2nd result :)
User avatar
xenopeek
Level 25
Level 25
Posts: 29459
Joined: Wed Jul 06, 2011 3:58 am

Re: log the exit code of a script after it completes[SOLVED]

Post by xenopeek »

I usually search for ^SHELL BUILTIN which jumps you to the right section immediately.

I also have a handy script somewhere that can display manpages in your web browser. That adds a table of contents to the manpage from which you can quickly jump to the right section on the page.
Image
Locked

Return to “Scripts & Bash”