9

Below is the script.

I wanted to login several servers and check for the kernel version.

#!/bin/bash
#input server names line by line in server.txt
cat server.txt | while read line
do
sshpass -p password ssh root@$line << EOF
hostname
uname -r
EOF
done

I would expect output which goes like..

server1_hostname
kernel_version
server2_hostname
kernel_version

and so on..

I ran this script with about 80 servers in server.txt

And the output i got was like.....

Pseudo-terminal will not be allocated because stdin is not a terminal. 
Pseudo-terminal will not be allocated because stdin is not a terminal.
Pseudo-terminal will not be allocated because stdin is not a terminal.
Pseudo-terminal will not be allocated because stdin is not a terminal.
Pseudo-terminal will not be allocated because stdin is not a terminal.
Pseudo-terminal will not be allocated because stdin is not a terminal.
Pseudo-terminal will not be allocated because stdin is not a terminal.
Pseudo-terminal will not be allocated because stdin is not a terminal.
Pseudo-terminal will not be allocated because stdin is not a terminal.

========================================================================
================================ WARNING ===============================
========================================================================
This system is solely for the use of authorized personnel. Individuals
using this system are subject to having some or all of their activities
monitored and recorded. Anyone using this system expressly consents to
such monitoring and is advised that any unauthorized or improper use of
this system may result in disciplinary action up to and including
termination of employment. Violators may also be subject to civil and/or
criminal penalties.
========================================================================

Warning: no access to tty (Bad file descriptor).
Thus no job control in this shell.
xxxxdev01
2.6.32-431.23.3.el6.x86_64
Pseudo-terminal will not be allocated because stdin is not a terminal.
Pseudo-terminal will not be allocated because stdin is not a terminal.
Pseudo-terminal will not be allocated because stdin is not a terminal.
Pseudo-terminal will not be allocated because stdin is not a terminal.
Pseudo-terminal will not be allocated because stdin is not a terminal.

Here I got output for only 1 host, which is xxxxdev01 and that too comes with the ssh banner and other warning.

I need output of all other hosts and without ssh banner.. What is going wrong here?

  • What happens if you use one of the servers manually and run sshpass -p password root@server histname ? – terdon Aug 23 '14 at 12:18
  • 1
    Use ssh -t -t root@... to force a pseudo-terminal. – garethTheRed Aug 23 '14 at 14:30
10

I can't tell you why you're not getting the expected output from the hostname and uname commands, but I can help with the extraneous text.

The "Pseudo-terminal" lines are being printed by ssh because it tries to allocate a TTY by default when no command to be executed was provided on the command line. You can avoid that message by adding "-T" to the ssh command:

sshpass -p password ssh -T root@$line

The "Warning: no access to tty" line is coming from the shell on the remote system. csh and tcsh will print that message under certain circumstances. It's possible that it's triggered by something in the .cshrc or similar file on the remote system, trying to access some feature which requires a TTY.

4

Use the following code,

#!/bin/bash
#input server names line by line in server.txt
cat server.txt | while read line
do
  sshpass -p password ssh root@$line 'hostname;uname -r'
done
  • This is what i tried first. But it doesn't give me the expected output. – Being Gokul Aug 24 '14 at 17:26
1

If your hosts are stored as follow in server.txt

host1.tld
host2.tld
....

You can

mapfile -t myhosts < server.txt; for host in "${myhosts[@]}"; do ssh username@"$host" 'hostname;uname -r'; done
1

The stdin is not accessible to your remote commands. What you can do is use "-s" flag of bash to read commands from the stdin:

From bash manual:

-s        If the -s option is present, or if no arguments remain after
          option processing, then commands are read from the standard 
          input.  This option allows the positional parameters to be set
          when  invoking  an  interactive shell.

So this should do what you want:

#!/bin/bash
#input server names line by line in server.txt
cat server.txt | while read line
do
    sshpass -p password ssh root@$line bash -s << EOF
hostname
uname -r
EOF
done

See also: https://stackoverflow.com/questions/305035/how-to-use-ssh-to-run-shell-script-on-a-remote-machine

1

This works great for me:

 # cat hostsname.txt 
operation01  172.20.68.37 5fDviDEwew
ngx-gw01     172.20.68.36 FiPp2UpRyu
gateway01    172.20.68.35 KeMbe57zzb
vehicle01    172.20.68.34 FElJ3ArM0m

# cat hostsname.txt | while read hostname ipaddr passwd; do sshpass -p $passwd /usr/bin/ssh-copy-id $ipaddr;done

note that use -t -t instead of -T to avoid the error

Pseudo-terminal will not be allocated because stdin is not a terminal

  • 1
    You ought to read up on formatting. Your answer might be excellent but just now it's pretty much unreadable. – roaima Mar 19 '17 at 15:10
0

I guess the ssh in the while eat up the rest to stdin. you may refer the Bash FAQ 89 for details. With a FileDescriptor, following codes should work as your expectation.

while read line <& 7
do
sshpass -p password ssh root@$line << EOF
hostname
uname -r
EOF
done 7< server.txt
  • the alternative way is to use /dev/null for ssh. FileDescriptor can be ignored. ` while read line; do sshpass -p password ssh root@$line < /dev/null << EOF .... done < server.txt` – Leon Wang Dec 16 '15 at 9:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.