Bash silent error processing - linux

I'm trying to run programs (for example mv file1.txt file2.txt) in my .sh script and I need to hide errors, but handle it with my script.
Currently I'm trying to do something like
EXECUTE="mv -v $VOL $BACKUP_YESTERDAY_CRYPT"
{
EXEC_ERROR=$($EXECUTE)
} &2>> $LOG_FILE
if [[ -n $EXEC_ERROR ]]; then
echo "There is an error!"
fi
But it doesn't work at all - it shows an error (for example mv: cannot stat 'file1.txt': No such file or directory) and $EXEC_ERROR variable is empty.
Is there any way to get output to variable + to log file?

How about something like:
mv -v $VOL $BACKUP_YESTERDAY_CRYPT 2>> $LOG_FILE
if [[ ! ( $? -eq 0 ) ]] ; then
echo "There is an error\!"
fi

Though $? is good for saving and processing exit codes, the if statement is designed to take any command, not just [ or [[:
if ! mv -v "$VOL" "$BACKUP_YESTERDAY_CRYPT" 2>> $LOG_FILE; then
echo "There is an error!"
fi
This includes saving variables:
if OUTPUT=$(mv -v "$VOL" "$BACKUP_YESTERDAY_CRYPT" 2>> $LOG_FILE); then
echo ">>> $OUTPUT <<<"
fi
In fact, if can take more than one command, as its man page describes. Documentation on boolean operators such as !, &&, and || is hidden within the description of shell commands, where they form pipelines (!) and lists (&&, ||).

Try this:
mv sourcefile destfile 2> /dev/null 1>logfile
returnstatus=`echo $?`
if [[ $returnstatus -ne 0 ]]; then
echo "There was an error!"
fi

Related

How to take output from a if condition?

I don't if this method is applicable or not.
#!/bin/bash
file=$1
if [[ -x "$file" ]]
then
if [ $? = 0 ]
then
echo $file is executable
else
echo $file is not executable
fi
fi
But if i run this script with a non executable file it returns nothing
But if i run this script with a executable file it returns "name is executable"
just want to know about positional parameter working. i'm a beginner.but can i
take the output of the first if condition into $?
For such test you do not need the internal if. THis code will do the work:
#!/bin/bash
file=$1
if [[ -x "$file" ]]
then
echo $file is executable
else
echo $file is not executable
fi

Stop grep message from posting

I am working on a script that take 1 string argument and a file. I want it so that if a file is put in that doesn't exist, then it will display the "filename cannot be read" message.
That part does work however it also displays a "grep: grep.txt: No such file or directory" message. Is there any way to stop the grep message from posting and ending the script if the first if statement is true?
#! /bin/sh
if [ ! -f "$2" ]
then
echo "$0" cannot be read 1>&2
fi
if [ $# -eq 2 ]
then
grep "$1" $2
else
echo there is more or less than 2 arguments 1>&2
fi
Exit the script with a non-zero exit code to indicate failure and stop it from continuing on to the grep.
if [ ! -f "$2" ]
then
echo "$0" cannot be read 1>&2
exit 1
fi
You can add /dev/null in grep command it will suppress the error part.
grep "$1" $2 2>/dev/null
The > operator redirects the output usually to a file but it can be to a device. You can also use >> to append.
2> file redirects stderr to file
/dev/null is the null device it takes any input you want and throws it away. It can be used to suppress any output.
You could redirect all errors from grep, for example:
grep "$1" $2 2>/dev/null
(the 2> means redirect standard error, as opposed to standard output with > or 1>).
That introduces a race condition, however: if the file disappears while your script as running, it might still exist when you check that it exists, but be gone by the time grep runs.
You could handle that by checking the exit status...
grep "$1" $2 2>/dev/null
if [[ $? -gt 1 ]]; then
echo "grep failed unexpectedly" >&2
fi
IMHO, in this example it would be better to just let grep print the error.

Symlink check - Linux Bash Script

I'm trying to create a script that searches through a directory to find symlinks that point to non-existing objects.
I have a file in a directory with a deleted symlink, but for some reason when i run the below script It says file exists.
#!/bin/bash
ls -l $1 |
if [ -d $1 ]
then
while read file
do
if test -e $1
then
echo "file exists"
else
echo "file does not exist"
fi
done
else
echo "No directory given"
fi
Thanks
Check this page. It has a test for broken links. It uses the -h operator to identify a symlink and the -e operator to check existance.
From that page:
linkchk () {
for element in $1/*; do
[ -h "$element" -a ! -e "$element" ] && echo \"$element\"
[ -d "$element" ] && linkchk $element
# Of course, '-h' tests for symbolic link, '-d' for directory.
done
}
# Send each arg that was passed to the script to the linkchk() function
#+ if it is a valid directoy. If not, then print the error message
#+ and usage info.
##################
for directory in $directorys; do
if [ -d $directory ]
then linkchk $directory
else
echo "$directory is not a directory"
echo "Usage: $0 dir1 dir2 ..."
fi
done
exit $?
You can test whether link is valid or not using:
[[ -f "$link" ]] && echo "points to a valid file"
To check if it is indeed a link use -L:
[[ -L "$link" ]] && echo "it's a link"
There seems to be a program named symlinks that does, among other things, what you're looking for.

restore in linux bash scripting

Help needed. This is script that I use to perform a restoration of a file from dustbin directory to its original location. It was located before in root. Then using other script it was "deleted" and stored in dustbin directory, and its former location was documented in storage file using this:
case $ans in
y) echo "`readlink -f $1`" >>home/storage & mv $1 /home/dustbin ;;
n) echo "File not deleted." ;;
*) echo "Please input answer." ;;
esac
So when using the script below I should restore the deleted file, but the following error comes up.
#!/bin/sh
if [ "$1" == "-n" ] ; then
cd ~/home/dustbin
restore="$(grep "$2" "$home/storage")"
filename="$(basename "$restore")"
echo "Where to save?"
read location
location1="$(readlink -f "$location")"
mv -i $filename "$location1"/$filename
else
cd ~/home
storage=$home/storage
restore="$(grep "$1" "$storage")"
filename="$(basename "$restore")"
mv -i $filename $restore
fi
error given - mv: missing file operand
EDIT:
so okay, I changed my script to something like this.
#!/bin/sh
if [ $1 ] ; then
cd ~/home
storage=~/home/storage
restore="$(grep "$1" "$storage")"
filename="$(basename "$restore")"
mv -i "$filename" "$restore"
fi
and still I get error:
mv: cannot stat `filename': No such file or directory
You might want to do some basic error handling to see if $filename exists before you use it as part of mv:
For example, before:
mv -i $filename "$location1"/$filename
You should probably do a:
if [[ -e "$filename" ]]; then
# do some error handling if you haven't found a filename
fi
The -e option checks whether the next argument to [[ refers to a filename that exists. It evaluates to true if so, false otherwise. (Alternatively, use -f to check if it's a regular file)
Or at least:
if [[ -z "$filename" ]]; then
# do some error handling if you haven't found a filename
fi
The -z option checks whether the next argument to [[ is the empty string. It evaluates to true if so, false otherwise.
Similar comment about: mv -i $filename $restore in your else clause.
Here's a list of test options.
You do
cd ~/home
and
mv -i "$filename" "$restore"
while the file is located in the dustbin directory, therefore, it is not found.
Do either
cd ~/home/dustbin
or
mv -i "dustbin/$filename" "$restore"
or just do
mv -i "~/home/dustbin/$filename" "$restore"
and drop the cd.

check if file exists on remote host with ssh

I would like to check if a certain file exists on the remote host.
I tried this:
$ if [ ssh user#localhost -p 19999 -e /home/user/Dropbox/path/Research_and_Development/Puffer_and_Traps/Repeaters_Network/UBC_LOGS/log1349544129.tar.bz2 ] then echo "okidoke"; else "not okay!" fi
-sh: syntax error: unexpected "else" (expecting "then")
In addition to the answers above, there's the shorthand way to do it:
ssh -q $HOST [[ -f $FILE_PATH ]] && echo "File exists" || echo "File does not exist";
-q is quiet mode, it will suppress warnings and messages.
As #Mat mentioned, one advantage of testing like this is that you can easily swap out the -f for any test operator you like: -nt, -d, -s etc...
Test Operators: http://tldp.org/LDP/abs/html/fto.html
Here is a simple approach:
#!/bin/bash
USE_IP='-o StrictHostKeyChecking=no username#192.168.1.2'
FILE_NAME=/home/user/file.txt
SSH_PASS='sshpass -p password-for-remote-machine'
if $SSH_PASS ssh $USE_IP stat $FILE_NAME \> /dev/null 2\>\&1
then
echo "File exists"
else
echo "File does not exist"
fi
You need to install sshpass on your machine to work it.
Can't get much simpler than this :)
ssh host "test -e /path/to/file"
if [ $? -eq 0 ]; then
# your file exists
fi
As suggested by dimo414, this can be collapsed to:
if ssh host "test -e /path/to/file"; then
# your file exists
fi
one line, proper quoting
ssh remote_host test -f "/path/to/file" && echo found || echo not found
You're missing ;s. The general syntax if you put it all in one line would be:
if thing ; then ... ; else ... ; fi
The thing can be pretty much anything that returns an exit code. The then branch is taken if that thing returns 0, the else branch otherwise.
[ isn't syntax, it's the test program (check out ls /bin/[, it actually exists, man test for the docs – although can also have a built-in version with different/additional features.) which is used to test various common conditions on files and variables. (Note that [[ on the other hand is syntax and is handled by your shell, if it supports it).
For your case, you don't want to use test directly, you want to test something on the remote host. So try something like:
if ssh user#host test -e "$file" ; then ... ; else ... ; fi
Test if a file exists:
HOST="example.com"
FILE="/path/to/file"
if ssh $HOST "test -e $FILE"; then
echo "File exists."
else
echo "File does not exist."
fi
And the opposite, test if a file does not exist:
HOST="example.com"
FILE="/path/to/file"
if ! ssh $HOST "test -e $FILE"; then
echo "File does not exist."
else
echo "File exists."
fi
ssh -q $HOST [[ -f $FILE_PATH ]] && echo "File exists"
The above will run the echo command on the machine you're running the ssh command from. To get the remote server to run the command:
ssh -q $HOST "[[ ! -f $FILE_PATH ]] && touch $FILE_PATH"
Silent check if file exist and perform if not
if ! ssh $USER#$HOST "test -e file.txt" 2> /dev/null; then
echo "File not exist"
fi
You can specify the shell to be used by the remote host locally.
echo 'echo "Bash version: ${BASH_VERSION}"' | ssh -q localhost bash
And be careful to (single-)quote the variables you wish to be expanded by the remote host; otherwise variable expansion will be done by your local shell!
# example for local / remote variable expansion
{
echo "[[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'" |
ssh -q localhost bash
echo '[[ $- == *i* ]] && echo "Interactive" || echo "Not interactive"' |
ssh -q localhost bash
}
So, to check if a certain file exists on the remote host you can do the following:
host='localhost' # localhost as test case
file='~/.bash_history'
if `echo 'test -f '"${file}"' && exit 0 || exit 1' | ssh -q "${host}" sh`; then
#if `echo '[[ -f '"${file}"' ]] && exit 0 || exit 1' | ssh -q "${host}" bash`; then
echo exists
else
echo does not exist
fi
I wanted also to check if a remote file exist but with RSH. I have tried the previous solutions but they didn't work with RSH.
Finally, I did I short function which works fine:
function existRemoteFile ()
{
REMOTE=$1
FILE=$2
RESULT=$(rsh -l user $REMOTE "test -e $FILE && echo \"0\" || echo \"1\"")
if [ $RESULT -eq 0 ]
then
return 0
else
return 1
fi
}
On CentOS machine, the oneliner bash that worked for me was:
if ssh <servername> "stat <filename> > /dev/null 2>&1"; then echo "file exists"; else echo "file doesnt exits"; fi
It needed I/O redirection (as the top answer) as well as quotes around the command to be run on remote.
This also works :
if ssh user#ip "[ -s /path/file_name ]" ;then
status=RECEIVED ;
else
status=MISSING ;
fi
#its simple
if [[ "`ssh -q user#hostname ls /dir/filename.abc 2>dev/null`" == "/dir/filename.abc" ]]
then
echo "file exists"
else
echo "file not exists"
fi

Resources