Script only processes 1st Line of input file [duplicate] - linux

This question already has answers here:
ssh breaks out of while-loop in bash [duplicate]
(2 answers)
Closed 4 years ago.
bash script to read a file and process commands remotely.
It currently only processes the first line (server1)
Need to remotely process 3 commands on server1 , then server2 ......
#!/bin/bash
while read line; do
sshpass -f password ssh -o StrictHostKeyChecking=no user#$line zgrep "^A30=" /var/tmp/logs1/messages.* | >> Output.txt
sshpass -f password ssh -o StrictHostKeyChecking=no user#$line zgrep "^A30=" /var/tmp/logs2/messages.* | >> Output.txt
sshpass -f password ssh -o StrictHostKeyChecking=no user#$line zgrep "^A30=" /var/tmp/logs3/messages.* | >> Output.txt
done < file1
file1:
server1
server2
server3

sshpass is reading from the same file descriptor as the while loop, and exhausting that input before read is able to read it. Best thing is to close its stdin explicitly sshpass <&- ... or redirect from /dev/null sshpass < /dev/null.
Another option is to let sshpass inherit stdin from the script and read from a different file descriptor:
while read line <&3; do
...
done 3< file1

Related

bash script | while loop breaks [duplicate]

This question already has answers here:
While loop stops reading after the first line in Bash
(5 answers)
Closed last year.
#!/bin/bash
input="/home/ptx/script/input.file"
while IFS= read -r line;
do
sshpass -f password_file ssh -tt admin#$line 'echo password | sudo -S -s ls -ltra &> collect.txt'
done < "$input"
password_file content:
password
input.file contents:
mescmb49
mescmb46
mescmb44
mescmb33
Question
need to collect remote servers home directory contents to remote server file.
want to automate this task.
all the servers are listed in input.file
issue is, once script works only for the first server that is "mescmb42"
sshpass is reading from its stdin, which it inherited from the while loop. So sshpass is consuming all of the data that you intended to go to read. The easiest fix is probably to close sshpass's input stream (or redirect it:
while IFS= read -r line; do
</dev/null sshpass ...
done < "$input"
while IFS= read -r line; do
<&- sshpass ...
done < "$input"
Another option is to have read read from an alternate fd:
while IFS= read -r line <&3; do
sshpass ...
done 3< "$input"

How to send email from remote server for particular user via unix shell script [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I need to send mail to a particular user from host computer via shell script using command line argument.Mail should go to that particular user only.
Script execution will be like ./tesh.sh user emailid
cat test.sh
#!/bin/sh
export user=$1
export email=$2
list=`echo "$(cat ip.txt)"`
script=$(cat remote_cmds.sh)
for ip in ${list[#]} ; do
echo "***";
echo "IP: $ip"
ssh -o StrictHostKeyChecking=no -l ${user} ${ip} ${script}
done
# cat remote_cmds.sh
source pathto/test.sh
echo "";
echo "****Hostname****";
echo "`hostname`";
echo "";
echo "****Disk Allocated****";
echo "`df -h`";
echo "";
echo "****Ram Allocated****";
echo testmail | mailx -s "Testmail" $email
If I understand you correctly you have N computers with ip addresses saved in ip.txt. Each of these computers has a user named 'user' to which you can login via ssh. Each of these computers has a user named 'emailid' to which you want to send mail. You want to use ssh session to connect to these computers and run mail client on these computers. You want to print some information about hostname, disc space and some other infos from the remote computers on your computer and send simple mail with subject 'Testmail' and content 'testmail' to the local user 'emaillid' on these remote N computers.
These scripts are not good. Doing script=$(cat remote_cmds.sh) and then calling ssh ... ${scripts} is so dangerous... The line list=echo "$(cat ip.txt)" can be just shortened to list=$(cat ip.txt). list variable is not an array, so doing ${list[#]} is the same as $list. remote_cmds.sh has the line source pathto/test.sh, so that means that each of N computers has a test.sh file in the same path?
mailx is giving you arror, cause you are executing (literally) mailx -s Testmail $email and email address can't have $ characters (the email variable is not expanded).
Try smth like this:
test.sh
#!/bin/sh
# export is not needed anywhere here
user=$1
email=$2
# loop through the lines in ip.txt
cat ip.txt | while read ip; do
echo "***";
echo "IP: $ip"
# https://unix.stackexchange.com/questions/87405/how-can-i-execute-local-script-on-remote-machine-and-include-arguments
# login on computer with ip $ip on user $user and execute command on
# remote host 'bash -s', which will read commands from standard input,
# append our remote_cmds.sh script to stdin and pass "$email" as first
# argument to this script
ssh -o StrictHostKeyChecking=no -l "$user" "$ip" bash -c -- < remote_cmds.sh "$email"
done
# this loop is bad and inefficient, but it's safe and simple to write
# see https://stackoverflow.com/questions/1521462/looping-through-the-content-of-a-file-in-bash
remote_cmds.sh
#!/bin/sh
# these lines will be executed on N computers
# email is passed as first argument to this script
email=$1
echo "";
echo "****Hostname****";
hostname
echo "";
echo "****Disk Allocated****";
df -h
echo "";
echo "****Ram Allocated****";
free -h # ;)
echo testmail | mailx -s "Testmail" "$email"

how to use value that is calculated inside ssh

I have linux script like below:
sshpass -p "pwd" ssh -tt user << 'EOF'
cd /directory
file=$(ls -1t | head -1)
exit
EOF
How to use the file parameter outside ssh. That is after EOF statement.
I think that you have to work with the output of the SSH command to capture it into a local variable.
This could be a viable solution (tried with obviously different parameters locally, OS Ubuntu 17.04):
CMD=`cat <<EOF
cd /directory
ls -1t | head -1
EOF`
FILE=`sshpass -p "pass" ssh -t user#host -o LogLevel=QUIET "$CMD"`
echo "$FILE"

shell script for remote connection to other system and execute bunch of command in it

I need a shell script that can take remote login in to a system and i can execute a bunch of commands in that system.
I made a script and actually it's working:
#!/bin/bash
USERNAME=KRUNAL
IP=10.61.162.241
ssh -l ${USERNAME} ${IP} "pwd "
ssh -l ${USERNAME} ${IP} "ls -la"
ssh -l ${USERNAME} ${IP} ./a.out
I have problem that if suppose i made script
ssh -l ${USERNAME} ${IP} "pwd " # this execute in remote system
ls -la # this execute in current system.
so every time i need ssh command to execute file on remote system.
Is there any way that i can run bunch of code in remote system with one time login.
You can send as much commands to ssh as you want, provided that you separate them with ; or linebreaks. So this should work:
ssh -l ${USERNAME} ${IP} "pwd; ls -la"
#Joao's suggestion works fine however its impractical when writing many lines.
If this is the case you can do
ssh -1 ${USERNAME} ${IP} bash << 'EOF'
cd /some/directory
./a.out
who am i
for i in `seq 1 10`
do
echo $i
done
EOF
Anything between 'EOF' and the final EOF will be executed in the server side.
You can also replace bash with csh or python and write code for that interpreter instead
If you want the output of the ssh session be stored in a file (say session.log) then replace
ssh -1 ${USERNAME} ${IP} bash << 'EOF'
with
ssh -1 ${USERNAME} ${IP} bash << 'EOF' > 'session.log'
rest remains unchanged

Bash script does not ssh all the entries of a csv file

I am trying to patch a bunch of CENT OS machines with the latest fix pack. I have the below bash script that takes csv file as a input which has the ip address and password for those machines.
The code works fine however, it would only work for the first row it does not seem to be working for the rest of the list as my output.txt only has the entry only for the first row host .
patch.sh
INPUT=hosts_test.cvs
OLDIFS=$IFS
IFS=,
[ ! -f $INPUT ] && { echo "$INPUT file not found"; exit 99; }
while read privateip password
do
sshpass -p$password ssh -t -o "StrictHostKeyChecking no" user123#$privateip "
hostname
hostname -I --all-ip-addresses
sudo yum -y update bash
env x='() { :;}; echo vulnerable' bash -c \"echo If you see the word vulnerable above, then you are vulnerable to shellshock\"
echo ""
exit
" >> output.txt
done < $INPUT
IFS=$OLDIFS
hosts_test.cvs
10.xxx.xx.219,abcd~qY1
10.xxx.xx.226,l4~abcdefg
10.xxx.xx.221,l4#abcdefgh
Terminal Output
Pseudo-terminal will not be allocated because stdin is not a terminal.
Add at the end of your sshpass command </dev/null.
Add Defaults:username !requiretty to your /etc/sudoers config
Get rid of -t from your ssh command
Optional, but recommended: set up public key auth so you don't have your passwords lying around in text files.
You can pass ssh another -t to force pty allocation:
ssh -t -t

Resources