Bash Script Error Catching

2020-05-26 10:52发布

问题:

I am very new to bash scripts, and for my first script attempt I am submitting files to my professor's dropbox within the same server.

The code is this:

#! /bin/bash
echo "Submit Lab$1? \c"

read choice

if [ $choice = "y" ]; then
   echo "Sending to Prof's dropbox..."
   cp -r /path/to/lab$1 /path/to/dropbox
else
   echo "Submission terminated."
fi

Usage for the command is simply "$ submit 1" (1 is a single integer, corresponding to which lab I want to submit)

The bash script appends the entered argument (a single integer) to the necessary filename (a directory), then submits that directory to my prof's dropbox using cp.

More for the sake of learning than of absolute necessity, I wanted to create a clean prompt that will catch any cp errors (such as file not existing), and be able to output my own error message.

So basically, something like:

echo "Submit lab$1?"

read choice

echo "Send to Prof's dropbox"
cp -rv /path/to/lab$1 /path/to/dropbox

<catch any errors from cp>

if [ cp has errors ]

   echo "Submission failed."

else if [ cp has no errors ]

   echo "Submission successful."

And so on...

I understand that I could use verbose mode, and that cp itself prints out errors, but as stated before, I'm doing this for the purpose of learning error catching in bash and being able to make a clean prompt.

Any help would be appreciated.

Thanks!


Also: I have a similar script which submits labs from my laptop, using scp. Assuming I have this question answered, can I apply the solutions to scp exactly the same way?

EDIT: I don't want cp errors to output to the shell! The most common error would probably be "cannot stat blah: no such file or directory." I would like to catch that error, and simply say "Submission failed."

EDIT #2: jcollado's answer is correct, the problem is on my part. Did not end the nested if-else with the proper "fi."

After fixing that up, it worked as intended. Still need to catch the error output but I believe I know where I need to go to figure that out on my own, so this question is answered as far as I'm concerned.

FINAL EDIT: Ah, what the heck - the redirect was so easy I figured I'd put the solution on here. If using Linux, simply add "2>/dev/null" (if you don't want error messages being saved in any file) after the cp to make "cp -r /first/path /second/path 2>/dev/null"

回答1:

Although you can test $?, you can also test the exit status of a command directly:

if cp -rv /path/to/lab$1 /path/to/dropbox
then echo Submission successful
fi
exit $?

The errors were already reported to standard error by cp. The exit shown will exit with status 0 (success) if cp was successful; otherwise, it exits with the status that cp exited with.

Clearly, you can wrap that in a loop if you want to, or you can make it non-interactive (but any exit terminates the script).



回答2:

To check the return code from the previous command, you can use the $? special variable as follows:

if [ "$?" -ne "0" ]; then
  echo "Submission failed"
  exit 1
fi

echo "Submission successful."

Additionally, if you want a clean prompt, you can redired stderr as explained here.

Finally, you can also use this in the script that uses scp, since it works regardless of the command you're using.



回答3:

echo "Submit lab$1?"

read choice

echo "Send to Prof's dropbox"
cp -rv /path/to/lab$1 /path/to/dropbox &>/dev/null

[ $? -eq 0 ] && { #success, do something } || { #fail, do something }

And so on...