SSH hot to check remote directory exist - bash

Idea is to check remote folder. Is it exist or no?
I try this
ssh -p 22 -tt user#server.com 'bash -d /home/test22
and it works fine
/home/test22: /home/test22: is a directory
Connection to server.com closed.
But when I try to use it with "IF" - it is wrong...always said "That directory exists"
#!/bin/bash
if [ "ssh -p 22 -tt user#server.com 'bash -d /home/test22'" ]; then
echo "That directory exists"
else
echo "That directory doesn't exists"
fi
Can you show correct example?
Thank you!

The command to use is not bash but test or its alias [:
if ssh -p 22 -tt user#server.com 'test -d /home/test22'; then
echo "That directory exists"
else
echo "That directory doesn't exists"
fi
The other important thing is that [] is not part of the if syntax. if is always followed by a command and if evaluates its exit status. So no need to surround your ssh command with [].
-d dir are actually the arguments of command test or [.
test -d dir
[ -d dir ]
are identical, the latter form requires a closing ] argument.

Related

While loop in bash script execute only once [duplicate]

This question already has answers here:
bash cycle breaks when calling ssh command in the loop
(2 answers)
Closed 3 months ago.
I have a given shell script:
#!/bin/bash
USERNAME=xenobot
SSH_KEY_LOCATION="~/.ssh/id_rsa"
FILE="server.info"
while read -r server_ip package_type; do
if [[ $package_type == "deb" ]]; then
echo "For $server_ip package type is $package_type"
DPKG_FILE_PATH=$(ls ./src/dpkg/dpkg-*)
DPKG_FILE=$(basename $DPKG_FILE_PATH)
echo "$DPKG_FILE located at $DPKG_FILE_PATH will be transfered via SSH to server"
scp ./src/dpkg/${DPKG_FILE} $USERNAME#$server_ip:/tmp
ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -l ${USERNAME} ${server_ip} "cd /tmp; sudo dpkg -i *.deb"
elif [[ $package_type == "rpm" ]]; then
echo "For $server_ip package type is $package_type"
RPM_FILE_PATH=$(ls ./src/rpm/rpm-*)
RPM_FILE=$(basename $RPM_FILE_PATH)
echo "$RPM_FILE located at $RPM_FILE_PATH will be transfered via SSH to server"
scp -o 'StrictHostKeyChecking no' ./src/rpm/${RPM_FILE} $USERNAME#$server_ip:/tmp
echo "$RPM_FILE has been successfuly transfered to server!"
ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -l ${USERNAME} ${server_ip} "cd /tmp; sudo rpm -ivh --force $RPM_FILE"
fi
done <"$FILE"
And I have following file server.info, from which previous shell script reads:
213.136.80.123 rpm 213.136.91.102 rpm
The problem with it, as it is execute only once from first line, and just stops there without executing the second line
I have tried just to print output from this server.info using the same while read -r and it seems that outputs just fine like this
#!/bin/bash
USERNAME=xenobot
SSH_KEY_LOCATION="~/.ssh/id_rsa"
FILE="server.info"
while read -r server_ip package_type; do
if [[ $package_type == "deb" ]]; then
echo "For $server_ip package type is $package_type"
elif [[ $package_type == "rpm" ]]; then
echo "For $server_ip package type is $package_type"
fi
done <"$FILE"
Output:
213.136.80.123 rpm 213.136.91.102 rpm
So it seems like it outputs two separate lines, however I do not know why it runs script only once in bigger example
Try using a different file descriptor for your list other than 0, 1, or 2 (in this case it's set to 3).
while read -r server_ip package_type <&3; do
...
done 3<"$FILE"
If that works, then what's going on here is that ssh -- being an interactive program -- is sucking up your STDIN input.

how can i expect ssh and run shell command?

i want to mkdir at remote machine, but i dont know if the dir exists, how can i do this?
i use spawn ssh username#ip bash -c [ -d $dest_file ] && echo ok || mkdir -p $dest_file
and returns
while executing
"-d $dest_file "
invoked from within
"[ -d $dest_file ] && echo ok || mkdir -p $dest_file"
(file "mkdir.exp" line 22)
i cant use ssh-key because my ip is dynamic
First, you probably don't need bash -c because ssh is already executing the command with your remote shell.
Secondly, you're not sufficiently quoting your ssh arguments. You're writing an expect script, which uses the tcl programming language, and [ is a special character that will attempt to evaluate its contents as a tcl command and return the output (read more here). For this to work properly, you would need to escape the opening [ to get tcl to interpret it literally:
spawn ssh localhost \[ -d $dest_file ] && echo ok || mkdir -p $dest_file
This seems to work correctly on my system, but as I indicate in a comment it would be much easier to drop all the conditionals and just run:
spawn ssh localhost mkdir -p $dest_file
This accomplishes the same thing and doesn't run afoul of any quoting issues.

How to change name of file if already present on remote machine?

I want to change the name of a file if it is already present on a remote server via SSH.
I tried this from here (SuperUser)
bash
ssh user#localhost -p 2222 'test -f /absolute/path/to/file' && echo 'YES' || echo 'NO'
This works well with a prompt, echoes YES when the file exists and NO when it doesn't. But I want this to be launched from a crontab, then it must be in a script.
Let's assume the file is called data.csv, a condition is set in a loop such as if there already is a data.csv file on the server, the file will be renamed data_1.csv and then data_2.csv, ... until the name is unique.
The renaming part works, but the detection part doesn't :
while [[ $fileIsPresent!='false' ]]
do
((appended+=1))
newFileName=${fileName}_${appended}.csv
remoteFilePathname=${remoteFolder}${newFileName}
ssh pi#localhost -p 2222 'test -f $remoteFilePathname' && fileIsPresent='true' || fileIsPresent='false'
done
always returns fileIsPresent='true' for any data_X.csv. All the paths are absolute.
Do you have any idea to help me?
This works:
$ cat replace.sh
#!/usr/bin/env bash
if [[ "$1" == "" ]]
then
echo "No filename passed."
exit
fi
if [[ ! -e "$1" ]]
then
echo "no such file"
exit
fi
base=${1%%.*} # get basename
ext=${1#*.} # get extension
for i in $(seq 1 100)
do
new="${base}_${i}.${ext}"
if [[ -e "$new" ]]
then
continue
fi
mv $1 $new
exit
done
$ ./replace.sh sample.csv
no such file
$ touch sample.csv
$ ./replace.sh sample.csv
$ ls
replace.sh
sample_1.csv
$ touch sample.csv
$ ./replace.sh sample.csv
$ ls
replace.sh
sample_1.csv
sample_2.csv
However, personally I'd prefer to use a timestamp instead of a number. Note that this sample will run out of names after 100. Timestamps won't. Something like $(date +%Y%m%d_%H%M%S).
As you asked for ideas to help you, I thought it worth mentioning that you probably don't want to start up to 100 ssh processes each one logging into the remote machine, so you might do better with a construct like this that only establishes a single ssh session that runs till complete:
ssh USER#REMOTE <<'EOF'
for ((i=0;i<10;i++)) ; do
echo $i
done
EOF
Alternatively, you can create and test a bash script locally and then run it remotely like this:
ssh USER#REMOTE 'bash -s' < LocallyTestedScript.bash

bash script which can ssh to a remote machine and execute commands, throws error when password is incorrect

I'm trying a bash script where i'm taking an argument of a file which has the IP address. I'm using sshpass, but with this i'm not able to know if ssh login was successful or not. Is there a way to check this ?
Please suggest if not sshpass, do i need to use any other cmd, to do remote login and execute cmds ?
Here is the snippet of the code :
#!/bin/bash
filename="$1"
while read -r line; do
sshpass -p 'test' ssh -o StrictHostKeyChecking=no test#$line 'df -h'
done < "$filename"
Have tried the suggested way to check $? value (if its incorrect password, $? value will be 5, however with valid or invalid password, shell script is not echoing 'wrong password', its always echoing "Can ssh to box- Password is correct" as per the following code :
#!/bin/bash
filename="$1"
while read -r line; do
sshpass -p 'test' ssh -o StrictHostKeyChecking=no test#$line 'df -h'
if [ $? -eq 5]
then
echo "Wrong password"
else
echo "Can ssh to box- Password is correct"
fi
done < "$filename"
My Requirement is to ssh to the remote box and execute commands. And in case, ssh fails i.e password is invalid, it need to print that password is invalid.
Use return value from sshpass.
According to man sshpass:
RETURN VALUES
As with any other program, sshpass returns 0 on success. In case of failure, the following return codes are used:
5 Invalid/incorrect password
After running sshpass, in bash return value from command is stored in $? variable.
Proof:
devilan#localhost:~ $ sshpass -p 'test' ssh smurf#localhost
devilan#localhost:~ $ echo $?
5
Sugested usage:
sshpass -p 'test' ssh smurf#localhost
if [ $? -eq 5 ]
then
echo "Wrong password"
else
echo "Something else"
fi
Space was missing after 5, and thus if condition wasn't getting evaluated successfully.
Here is the modified code which works :
filename="$1"
while read -r line; do
sshpass -p 'test' ssh -o StrictHostKeyChecking=no test#$line 'df -h'
if [ $? -eq 5 ]
then
echo "Wrong password"
else
echo "Can ssh to box- Password is correct"
fi
done < "$filename"

How do I sudo if in Bash?

I need to check for a directory in the home directory of another user. Normally I would sudo but that forks another process and I also lose my environment.
For example, I have:
if [[ -d "/home/otheruser/svn" ]];
then
echo "SVN exists"
else
echo "SVN does not exist"
fi
I need the the test condition to run with root permissions.
if sudo test -d "/home/otheruser/svn"; then
You need to run it under a subshell. Example:
if sudo bash -c '[[ -d "/home/otheruser/svn" ]]'
then
echo "SVN exists"
else
echo "SVN does not exist"
fi

Resources