SSH into remote computer and compile/run code - bash

I made a script (below) that goes into a remote computer and runs C code on it. This script works perfectly but asks for the password multiple times. How can I make it only ask for the password once?
#!/bin/bash
USER=myusername
COMP=remote_computer_name
OUTPUT=$1
ARGS=${#:2}
CODE_DIR="Dir_$$"
SCRIPT_NAME=$(basename $0)
LAST_CREATED_DIR=$(ls -td -- */ | head -n 1)
#Check if we are on local computer. If so, we copy the
#current directory to the remote run this script on the remote
if [ "${HOSTNAME}" != "${COMP}" ]; then
if [ "$#" -lt 1 ]; then
echo "Incorrect usage."
echo "Usage: ./${SCRIPT_NAME} <compiled_c_output_name> <arg1> <arg2> ... <argN>"
exit
fi
# Check if there is no makefile in the current directory
if [ ! -e [Mm]akefile ]; then
echo "There is no makefile in this directory"
exit
fi
echo "On local. Copying current directory to remote..."
scp -r ./ ${USER}#${COMP}:/ilab/users/${USER}/${CODE_DIR}
ssh ${USER}#${COMP} "bash -s" < ./${SCRIPT_NAME} ${OUTPUT} ${ARGS}
else
echo "On remote. Compiling code..."
cd $LAST_CREATED_DIR
make clean
make all
if [ -e $OUTPUT ]; then
echo "EXECUTING \"./${OUTPUT} ${ARGS}\" ON REMOTE ($COMP)"
./${OUTPUT} ${ARGS}
fi
fi

You can use SSH-Key authentication technique for password less login -
Here are the steps :
Generate RSA key -
ssh-keygen -t rsa
This generates two files under /home/<user>/.ssh/ id_rsa
(Private) and id_rsa.pub (Public)
The second file is your public key. You have to copy the contents of
this file over to the remote computer you want to log into and append
it to /home/<user>/.ssh/authorized_keys or use ssh-copy-id
utility if available (ssh-copy-id username#remote_host)
After this, the authentication is done by the public-private key pair
and you may not require a password henceforth.

You can use sshpass. Here is an example:
sshpass -pfoobar ssh -o StrictHostKeyChecking=no user#host command_to_run
More info, here:
https://askubuntu.com/questions/282319/how-to-use-sshpass

Related

run 2 rsync commands and print the output to a log file

I'm new to scripting and would like to understand how to print out the variables based on boolean logic.
#!/bin/bash
# set variables
WEBAPPS_YES="Successfully synced webapps folder"
WEBAPPS_NO="Could not sync webapps folder"
RSYNC_YES="Successfully synced rsync log file"
RSYNC_NO="Could not sync rsync log file"
# Command to rsync 'webapps' folder and write to a log file
rsync -azvh ~/webapps -e ssh user#something.com:/home/directories >> /path/to/rsync.log 2>&1
# Command to rsync 'rsync.log' to a log file on backup server 'Larry'
rsync -azvh --delete ~/rsync.log -e ssh user#something.com:/path/to/logs
if [ $? -eq 0 ]
then
echo
exit 0
else
echo >&2
exit 1
fi
I would like the whole if, then, else part to print out in the echo if both parts succeeded or not. I know I need some kind of logic statements but cannot figure it out.
You can check the result after running each rsync command, and display the result afterwards. I think that would work:
# Command to rsync 'webapps' folder and write to a log file
rsync -azvh ~/webapps -e ssh user#something.com:/home/directories >> /path/to/rsync.log 2>&1
RESULT1="$?"
# Command to rsync 'rsync.log' to a log file on backup server 'Larry'
rsync -azvh --delete ~/rsync.log -e ssh user#something.com:/path/to/logs
RESULT2="$?"
if [ "$RESULT1" != "0" ]; then
echo "$WEBAPPS_NO"
else
echo "$WEBAPPS_YES"
fi
if [ "$RESULT2" != "0" ]; then
echo "$RSYNC_NO"
else
echo "$RSYNC_YES"
fi

How do I check to see if a file exists on a remote server using shell

I have done a lot of searching and I can't seem to find out how to do this using a shell script. Basically, I am copying files down from remote servers and I want to do something else if it doesn't exist. I have an array below, but I tried to reference it directly, but it is still returning false.
I am brand new at this, so please be kind :)
declare -a array1=('user1#user1.user.com');
for i in "${array1[#]}"
do
if [ -f "$i:/home/user/directory/file" ];
then
do stuff
else
Do other stuff
fi
done
Try this:
ssh -q $HOST [[ -f $i:/home/user/directory/file ]] && echo "File exists" || echo "File does not exist";
or like this:
if ssh $HOST stat $FILE_PATH \> /dev/null 2\>\&1
then
echo "File exists"
else
echo "File not exist"
fi
Assuming you are using scp and ssh for remote connections something like this should do what you want.
declare -a array1=('user1#user1.user.com');
for i in "${array1[#]}"; do
if ssh -q "$i" "test -f /home/user/directory/file"; then
scp "$i:/home/user/directory/file" /local/path
else
echo 'Could not access remote file.'
fi
done
Alternatively, if you don't necessarily need to care about the difference between the remote file not existing and other possible scp errors then the following would work.
declare -a array1=('user1#user1.user.com');
for i in "${array1[#]}"; do
if ! scp "$i:/home/user/directory/file" /local/path; then
echo 'Remote file did not exist.'
fi
done

How to execute bash script after rsync

When I deploy on my dev server I use rsync. But after rsync I need to execute a .sh file for "after" deploy operations like clear cache...
Usually I do this via SSH, but if I deploy very often it's boring write:
ssh ...
write password
cd /var/www/myapp/web
./after_deploy.sh
There is a way to do this quickly? This is my rsync.sh:
#!/bin/bash
host=""
directory="/var/www/myapp/web"
password=""
usage(){
echo "Cant do rsync";
echo "Using:";
echo " $0 direct";
echo "Or:";
echo " $0 dry";
}
echo "Host: $host";
echo "Directory: $directory"
if [ $# -eq 1 ]; then
if [ "$1" == "dry" ]; then
echo "DRY-RUN mode";
rsync -CvzrltD --force --delete --exclude-from="app/config/rsync_exclude.txt" -e "sshpass -p '$password' ssh -p22" ./ $host:$directory --dry-run
elif [ "$1" == "direct" ]; then
echo "Normal mode";
rsync -CvzrltD --force --delete --exclude-from="app/config/rsync_exclude.txt" -e "sshpass -p '$password' ssh -p22" ./ $host:$directory
else
usage;
fi;
else
usage;
fi
If instead of using rsync over SSH, you can run an rsync daemon on the server. This allows you to use the pre-xfer exec and post-xfer exec options in /etc/rsyncd.conf to specify a command to be run before and/or after the transfer.
For example, in /etc/rsyncd.conf:
[myTransfers]
path = /path/to/stuff
auth users = username
secrets file = /path/to/rsync.secrets
pre-xfer exec = /usr/local/bin/someScript.sh
post-xfer exec = /usr/local/bin/someOtherscript.sh
You can then do the transfer from the client machine, and the relevant scripts will be run automatically on the server, for example:
rsync -av . username#hostname::myTransfers/
This approach may also be useful because environment variables relating to the transfer on the server can also be used by the scripts.
See https://linux.die.net/man/5/rsyncd.conf for more information.
You can add a command after the rsync command to execute it instead of starting a shell.
Add the following after the rsync command :
sshpass -p "$password" ssh $host "cd $dir && ./after_deploy.sh"

rdiff-backup errors: script keeps quitting with error

Ive recently been introduced to bash scripting... So, Ive used my advanced theft course to throw together the attached script. it runs... and exits with "/xxx/ not mounted. You are not root! I have rdiff-backup and sshfs installed and working. The commands work fine on their own on the commandline, but in the script, well... Can you guys take a look and lemme know? PS I copied a LOT of this from scripts I found here and a few other places.
<code>
#!/bin/bash
# Version 1.5
# Prior to running this make sure you have ssh-keygen -t rsa to generate a key, then
# ssh username#target "mkdir .ssh/;chmod 700 .ssh"
# scp .ssh/id_rsa.pub username#target:.ssh/authorized_keys
#
# then check you can login and accept the ssh key
# ssh username#target "ls -la"
#
# Key things to remember, no spaces in pathnames, and try to use full paths (beginning with / )
#
# variables determine backup criteria
DATESTAMP=`date +%d%m%y`
USERNAME=username #remote site username here
TARGET=remote.ip.here #add the ip v4 address of the target
INCLUDES=/path/to/file/includes.txt #this is a txt file containing a list of directories you want backed up
EXCLUDES="**" #this is a list of files etc you want to skip
BACKUPLOG=/path/to/logfile/in/home/backuplog${DATESTAMP}.txt
OLDERTHAN=20W #change 20 to reflect how far back you want backups to exist
# to activate old backup expiry, uncomment the line below
#RMARGS=" --force --remove-older-than ${OLDERTHAN}"
TARGETMAIL="yourmailaddress#your.domain"
HOSTNAME=`hostname` #Dont change this!
TMPDIR=/backups Change this to the source folder
TARGETFOLDER=/backups change this to the TARGET folder
ARGS=" -v0 --terminal-verbosity 0 --exclude-special-files --exclude-other-filesystems --no-compression -v6"
# detecting distro and setting the correct path
if [ -e /etc/debian_version ];then
NICE=/usr/bin/nice
elif [ -e /etc/redhat-release ];then
NICE=/bin/nice
fi
if [ -e /tmp/backup.lock ];then
exit 0
fi
touch /tmp/backup.lock
touch -a ${BACKUPLOG}
cd /
/bin/mkdir -p ${TMPDIR}
/usr/bin/sshfs -o idmap=user -o ${USERNAME}#${TARGET}:/${TARGETFOLDER} ${TMPDIR} &>${BACKUPLOG}
# if you get errors mounting this then try
# mknod /dev/fuse -m 0666 c 10 229
for ITEMI in ${INCLUDES} ; do
ARGS="${ARGS} --include ${ITEMI} "
done
for ITEME in ${EXCLUDES} ; do
ARGS="${ARGS} --exclude-regexp '${ITEME}' "
done
# the --exclude ** / is a hack because it wont by default do multiple dirs, so use --include for all dirs then exclude everything else and sync / - if you dont understand dont worry
# ref: http://www.mail-archive.com/rdiff-backup-users#nongnu.org/msg00311.html
#echo /usr/bin/rdiff-backup ${ARGS} --exclude \'**\' / ${TMPDIR}/ &&
cat ${INCLUDES} | while read DIR; do
${NICE} -19 /usr/bin/rdiff-backup --exclude '**' ${DIR} ${TMPDIR}/ &>${BACKUPLOG}
if [ $? != 0 ]; then
echo "System Backup Failed" | mutt -s "Backup Log: System Backup Failed, Log attached!" -a ${BACKUPLOG} ${TARGETMAIL}
exit 1;
fi
done
#${NICE} -19 /usr/bin/rdiff-backup ${ARGS} --exclude '**' / ${TMPDIR}/ &>${BACKUPLOG} &&
echo Removing backups older than ${RMARGS}
${NICE} -19 /usr/bin/rdiff-backup -v0 --terminal-verbosity 0 ${RMARGS} ${TMPDIR}/ &>${BACKUPLOG}
/bin/umount ${TMPDIR} && /bin/rm -rf ${TMPDIR}/ &>${BACKUPLOG}
echo "System Backup Run" | mutt -s "Backup Log: System Backup Done!" -a ${BACKUPLOG} ${TARGETMAIL}
rm /tmp/backup.lock
rm ${BACKUPLOG}
Sorry, cannot paste, couldnt attach... BLIKSEM!
Thanks for ANY input... One HELL of a learning curve!!!
Regards,
B.

how to find a file exists in particular dir through SSH

how to find a file exists in particular dir through SSH
for example :
host1 and dir /home/tree/TEST
Host2:- ssh host1 - find the TEST file exists or not using bash
ssh will return the exit code of the command you ask it to execute:
if ssh host1 stat /home/tree/TEST \> /dev/null 2\>\&1
then
echo File exists
else
echo Not found
fi
You'll need to have key authentication setup of course, so you avoid the password prompt.
This is what I ended up doing after reading and trying out the stuff here:
FileExists=`ssh host "test -e /home/tree/TEST && echo 1 || echo 0"`
if [ ${FileExists} = 0 ]
#do something because the file doesn't exist
fi
More info about test: http://linux.die.net/man/1/test
An extension to Erik's accepted answer.
Here is my bash script for waiting on an external process to upload a file. This will block current script execution indefinitely until the file exists.
Requires key-based SSH access although this could be easily modified to a curl version for checks over HTTP.
This is useful for uploads via external systems that use temporary file names:
rsync
transmission (torrent)
Script below:
#!/bin/bash
set -vx
#AUTH="user#server"
AUTH="${1}"
#FILE="/tmp/test.txt"
FILE="${2}"
while (sleep 60); do
if ssh ${AUTH} stat "${FILE}" > /dev/null 2>&1; then
echo "File found";
exit 0;
fi;
done;
No need for echo. Can't get much simpler than this :)
ssh host "test -e /path/to/file"
if [ $? -eq 0 ]; then
# your file exists
fi

Resources