Is there a way that you can use the "if" branch to check whether a USB stick is connected? - linux

Is there a way like that you can use the "if" branch to check whether a USB-Stick is connected? And if the stick is not connected, a message should then be issued.
Something like:
if [-e /sdb1]
then
cp /home/backup/* /sdb1
rm -r /home/backup/*
echo "your files are successfully transferred."
else
echo "please be sure, if your USB-Stick is connected"
fi

No, the mount point exists whether or not a USB device is connected.
Something like this should suffice:
if [[ $(df | grep "/sdb1") && -d /sdb1 && -w /sdb1 ]]
That is if, of course, you have actually created the directory /sdb1/.

Use the findmnt utility (installed by default on RH and Ubuntu, at least)
findmnt /backup
echo $?
1
Return of 1 means not mounted.
Here is some sample code using it with an if statment
findmnt /backup >/dev/null
if [ $? = 0 ]; then
echo "It's mounted all right"
else
r=$(( RANDOM % 4 ))
echo "USB is not mounted."
case $r in
0) echo "Check the couch cushions."
;;
1) echo "I think I saw it in the kitchen."
;;
2) echo "Sign up for Prime and get free shipping!"
;;
3) echo "The dog ate it."
;;
esac
fi

Related

How to read command output and use it silently on a bash script?

I'm new on bash. I want to write a script which will run iwconfig command the output should show me my wlan* mode is Managed or Monitor?
I had tried this like following but it is not working and runs the command output. I just need to echo which mode is it.
IWCONFIG_LOG="$(iwconfig)"
if [[ "$IWCONFIG_LOG" == *Mode:Managed* ]]; then
echo "Managed"
elif [[ "$IWCONFIG_LOG" == *Mode:Monitor* ]]; then
echo "Monitor Mode"
fi
Looks like you want to use Bash (not sh) in order to get this accomplish.
So, try this:
#!/bin/bash
IWCONFIG_LOG="$((iwconfig | grep Mode) 2> /dev/null)"
if [[ $IWCONFIG_LOG == *"Mode:Managed"* ]]; then
echo "Managed"
elif [[ $IWCONFIG_LOG == *"Mode:Monitor"* ]]; then
echo "Monitor Mode"
fi
Save it as a file and chmod 755 it to make it executable or execute it using "bash" instead "sh".
There are several modes, not only Managed or Monitor, so seems you only want to detect one of these two.
To see all available modes read man iwconfig
Since iwconfig writes also to standard error:
if [[ $(iwconfig 2>/dev/null | grep "Managed") ]]; then
echo "Managed"
else
echo "Monitor"
fi
or, as pointed out by #choroba in comments:
if iwconfig 2>/dev/null | grep -q Managed ; then
echo "Managed"
else
echo "Monitor"
fi

What have i done wrong here? or is there a better alternitive to $answer?

Lately ive been busy playing around with bash on my linux operating system, and im also using it too sort files. But this does not seem to work. Is there an alternitive way of what im doing or is it wrong?
echo -n "Are you sure you would like to delete this/these files? [y/n]"
if [ $answer == "y" ]; then
echo -n "Which File would you like to delete?"
rm $answer
else
echo "canceled!"
fi
Check the following usage of "read" command
read -n1 -p "Are you sure you would like to delete this/these files? [y/n]: " answer
if [ "$answer" == "y" ]; then
read -p "Which File would you like to delete: " filename
rm $filename
else
echo "cancelled!"
fi

Repeat command in linux script if there is an error for google cloud console tools [duplicate]

I have a script and want to ask the user for some information, but the script cannot continue until the user fills in this information. The following is my attempt at putting a command into a loop to achieve this but it doesn't work for some reason:
echo "Please change password"
while passwd
do
echo "Try again"
done
I have tried many variations of the while loop:
while `passwd`
while [[ "`passwd`" -gt 0 ]]
while [ `passwd` -ne 0 ]]
# ... And much more
But I can't seem to get it to work.
until passwd
do
echo "Try again"
done
or
while ! passwd
do
echo "Try again"
done
To elaborate on #Marc B's answer,
$ passwd
$ while [ $? -ne 0 ]; do !!; done
Is nice way of doing the same thing that's not command specific.
You need to test $? instead, which is the exit status of the previous command. passwd exits with 0 if everything worked ok, and non-zero if the passwd change failed (wrong password, password mismatch, etc...)
passwd
while [ $? -ne 0 ]; do
passwd
done
With your backtick version, you're comparing passwd's output, which would be stuff like Enter password and confirm password and the like.
If anyone looking to have retry limit:
max_retry=5
counter=0
until $command
do
sleep 1
[[ counter -eq $max_retry ]] && echo "Failed!" && exit 1
echo "Trying again. Try #$counter"
((counter++))
done
You can use an infinite loop to achieve this:
while true
do
read -p "Enter password" passwd
case "$passwd" in
<some good condition> ) break;;
esac
done
while [ -n $(passwd) ]; do
echo "Try again";
done;

Bash Script - Check mounted devices

What I'm trying to do -
In the end, I want a script that checks for 3 devices, an SD card, Backup1 & Backup2. They've all been set to auto-mount at their respective mountpoints. The script should check for SD card first, if this fails, then a warning should be sent, and nothing more. If SD is okay, but only one backup is mounted, then ask for confirmation to go ahead with rsync to mounted backup. If all devices are mounted, then rsync from SD card to both backups.
Currently I'm just trying to get the device check nailed, using echo commands. Here's what I have (after multiple attempts) -
if ! mount | grep /media/card >/dev/null
then
echo "ERROR: SD card not mounted, aborting"
else
if ! mount | grep /media/backup >/dev/null
then
if ! mount | grep /media/backup2 >/dev/null
then
echo "ERROR: No backup devices"
else
echo "CAUTION: Backup_2 missing, Backup_1 OKAY"
fi
else
if ! mount | grep /media/backup2 /dev/null
then
echo "CAUTION: Backup_1 missing, Backup_2 OKAY"
else
echo "SUCCESS: All devices OKAY"
fi
fi
fi
Which isn't working. I'm getting confused by all the nested 'if's and surely there's a simpler way? Perhaps something that checks each device independently, then returns values that equate to the various combinations (0=no devices, 1=sd only, 2=sd & backup1, 3=sd & backup 2, 4 = all okay) which then is read and decides next part of script to run? If not, where has this way gone wrong?
Any help is appreciated
Use mountpoint, which returns success (0) if the path is a mounted device, and 1 otherwise:
#!/bin/bash
check_mountpoint(){
if mountpoint -q $1
then
printf "%s\n" "$1 is mounted"
return 0
else
printf "%s\n" "$1 is not mounted"
return 1
fi
}
check_mountpoint /media/sd
if [ $? -gt 0 ]
then
printf "%s\n" "aborting"
exit 0
fi
check_mountpoint /media/backup1
check_mountpoint /media/backup2
this is your code corrected, i hope it will help.
if mountpoint -q /media/sd
then
if mountpoint -q /media/backup
then
if mountpoint -q /media/backup2
then
echo "SUCCESS: All devices OKAY"
# run your command here
else
echo "CAUTION: Backup_2 missing, Backup_1 OKAY, SD OKAY"
# run your command here
fi
else
if mountpoint -q /media/backup2
then
echo "CAUTION: Backup_1 missing, Backup_2 OKAY, SD OKAY"
# run your command here
else
echo "SD OKAY , BACKUP Devices missing"
fi
fi
else
echo "SD is missing , Exit"
fi
Solved! Part of the problem was using mount | grep /media/backup > /dev/null as there's an issue with similar names, so /media/backup2 being mounted meant it was counting both devices as mounted.
Using grep -q /media/backup2\ /proc/mounts works in a similar way, or at least produces the same outcome, just without the naming issue.
I've also changed the way the if statements work, it now checks for SD card, if that fails, then it aborts. It then checks for which devices are mounted with a fairly simple flow.
Here's the code:
GNU nano 2.2.6 File: backupSD2.sh Modified
#!/bin/bash
#Check for SD
if ! grep -q /media/card\ /proc/mounts
then
echo "ERROR: NO SD CARD"
exit 0
else
echo "SD OKAY..."
fi
#Check for Backup Devices
if (( grep -q /media/backup\ /proc/mounts ) && ( grep -q /media/backup2\ /proc/mounts ))
then
echo "Both Backups mounted"
elif grep -q /media/backup\ /proc/mounts
then
echo "CAUTION: Backup_2 missing, Backup_1 OKAY"
elif grep -q /media/backup2\ /proc/mounts
then
echo "CAUTION: Backup_1 missing, Backup_2 OKAY"
else
echo "ERROR: NO BACKUP DEVICES"
exit 0
fi
After the 'echo' commands is where I'll be putting the rsync commands.
The final exit 0 is probably unnecessary, but I don't think it's doing any harm and reassures that it's not going to try any more commands.
Check for 1 required mounted source AND at least 1 required mounted target
The best aproach for this is to build an array of mounted devices, then evaluate de count of elements in array.
Introduction
1. Care! Using grep -q "$dev" /proc/mounts will fail to found spaced mount points!
/media/spaced target
in /proc/mounts will appear as
/media/spaced\040target
command printf -v varname '%b' $varname could help!
2. Using bash array and associative array to avoid fork
Instead of doing many fork to grep, (browsing same file many time), you could use bash for the job.
3. Parallelizing rsync on many targets
Using backgrounded jobs and wait -n -p <VARNAME>, you could do rsync on many targets simultaneously.
4. Using /proc/self/mounts instead of /proc/mounts
After having a look at man 5 proc.
Here is a script, within:
you could configure as many backup targets you want.
if all targets are mounted, script go on
if no targets are mounted, script stop and
if at least one target is mounted but not all, user is asked for continuing.
(this could be avoided by using -y/-n optional flag)
On second part, all rsync are run as background job (parallelized),
then script wait for all rsync to be done,
then print each result code with corresponding target,
before finish
The script:
#!/bin/bash
source='/media/card'
backups=(
/media/backup
/media/backup2
/media/other\ backup
)
die() {
echo "$0[$$] ERROR: $#" >&2
exit 1
}
warn() {
echo "$0[$$] WARNING: $#" >&2
}
declare -A tobemounted="(['$source']='source')"
for target in "${backups[#]}";do
tobemounted["$target"]=backup
done
mountedbk=()
while read -r _ mpnt _;do
printf -v mpnt %b $mpnt
if [[ -v tobemounted["$mpnt"] ]] ;then
[[ ${tobemounted["$mpnt"]} == backup ]] && mountedbk+=("$mpnt")
unset tobemounted["$mpnt"]
fi
done </proc/self/mounts
[[ -v tobemounted["$source"] ]] && die "Source '$source' not mounted."
for missing in "${!tobemounted[#]}";do
warn "Backup '$missing' not mounted."
done
(( ${#mountedbk[#]} == 0 )) && die "No backup present."
if (( ${#mountedbk[#]} < ${#backups[#]} ));then
printf -v msg 'Only %d / %d backups targets are present.' \
${#mountedbk[#]} ${#backups[#]}
warn "$msg"
case $* in
*-n* ) die Exit now. ;;
*-y* ) warn Process anyway. ;;
* ) read -rsn 1 -p 'Process anyway? (N/y): ' ans
[[ "${ans//[yY]}" ]] && { echo No; die 'User abort.';}
echo Yes ;;
esac
fi
pids=() resultmsg=(success)
for target in "${mountedbk[#]}";do
echo rsync "$source/." "$target/." &
pids[$!]="$target"
done
while ((${#pids[#]}));do
wait -np pid
printf 'backup to "%s" end with %s.\n' \
"${pids[pid]}" "${resultmsg[$?]:-error}"
unset 'pids[pid]'
done
Replace line:
echo rsync "$source/." "$target/." &
by somethine like:
rsync <your rsync options> "$source/SourcePath/." "$target/TargetPath/." &
Outputs could look like:
When source not ready:
$ ./backups.sh
./backups.sh[3721068] ERROR: Source '/media/card' not mounted.
When none of the targets are ready.
$ ./backups.sh
./backups.sh[3729071] WARNING: Backup '/media/backup' not mounted.
./backups.sh[3729071] WARNING: Backup '/media/backup2' not mounted.
./backups.sh[3729071] WARNING: Backup '/media/other backup' not mounted.
./backups.sh[3729071] ERROR: No backup present.
When some but not all targets are ready.
$ ./backups.sh
./backups.sh[3725569] WARNING: Backup '/media/backup2' not mounted.
./backups.sh[3725569] WARNING: Backup '/media/other backup' not mounted.
./backups.sh[3725569] WARNING: Only 1 / 3 backups targets are present.
Process anyway? (N/y): Yes
backup to "/media/backup" end with success.
$ ./backups.sh
./backups.sh[3729355] WARNING: Backup '/media/backup' not mounted.
./backups.sh[3729355] WARNING: Backup '/media/other backup' not mounted.
./backups.sh[3729355] WARNING: Only 1 / 3 backups targets are present.
Process anyway? (N/y): Yes
backup to "/media/backup2" end with success.
$ ./backups.sh
./backups.sh[3854708] WARNING: Backup '/media/backup2' not mounted.
./backups.sh[3854708] WARNING: Backup '/media/other backup' not mounted.
./backups.sh[3854708] WARNING: Only 1 / 3 backups targets are present.
Process anyway? (N/y): No
./backups.sh[3854708] ERROR: User abort.
$ ./backups.sh -y
./backups.sh[3734321] WARNING: Backup '/media/backup' not mounted.
./backups.sh[3734321] WARNING: Backup '/media/other backup' not mounted.
./backups.sh[3734321] WARNING: Only 1 / 3 backups targets are present.
./backups.sh[3734321] Process anyway.
backup to "/media/backup2" end with success.
$ ./backups.sh -n
./backups.sh[3854855] WARNING: Backup '/media/backup2' not mounted.
./backups.sh[3854855] WARNING: Backup '/media/other backup' not mounted.
./backups.sh[3854855] WARNING: Only 1 / 3 backups targets are present.
./backups.sh[3854855] ERROR: Exit now.
When all targets are ready.
$ ./backups.sh
backup to "/media/backup" end with success.
backup to "/media/backup2" end with success.
backup to "/media/other\ backup" end with success.

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