Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a list of IP address that I need to SSH to and log if I could get to them. I would use a Ping script, but DNS might have already reassigned the address. I do not care about the ones I can't get to. If the SSH works I need to log that IP address, I shouldn't have to worry about passwords or keys because I don't want to log in to the box's. I just want to see if I can SSH to them. So far i have:

touch logfile_$(date "+%Y%m%d%T")
IP_FILE="path/to/ip_address.txt"
LOGFILE="path/to/logfile_$(date "+%Y%m%d%T")"


if [[ ! -f ${IP_FILE} ]]; then
   echo "Cannot find IP address!"
   exit 1
fi

for IP_ADDRESS in `cat $IP_FILE` ; do

    ssh $IP_ADDRESS >> $LOGFILE 2>&1

I am still new to scripting and any help would be great. I have looked at "How to check if I can log in to server via ssh?" posted by LanceBaynes but its not really what I need.

I can't install anything on this boxes. Or I would have downloaded a nice scanner. Like Netcat or Nmap both of which are great options.

share|improve this question
    
What's the reason for you not being able to install anything on the server you're testing the connections from?? –  EightBitTony Jul 5 '13 at 13:53
    
company policy. I could put in the paper work but that would take months. –  Dolyak Jul 5 '13 at 14:20
    
Seriously? You have a policy that precludes administrators from installing whatever software they happen to need? No offense, but what kind of mindblowingly idiotic corporate entity do you have the misfortune to work for? –  terdon Jul 5 '13 at 14:25
    
ya it really sucks. I cant tell you were I work for I am sorry. –  Dolyak Jul 5 '13 at 14:35
    
@terdon - if you work with systems that deal with PCI compliance this isn't that unusual! He probably works for a place that gives him a pay check, and there are very good reasons for limiting exposure in this manner. Careful what you assume! –  slm Jul 5 '13 at 14:41
show 3 more comments

4 Answers

up vote 6 down vote accepted

Method #1: ssh-keyscan

One method would be to use the command ssh-keyscan to see if a ssh daemon is up and functioning.

Just loop through the IP addresses and ssh-keyscan <ip> | grep -v ... each server. If the server is there, the status returned by running the ssh-keyscan ... | grep -v ... command will be a 0, anything else (1 or higher) means there isn't a server there.

Example

$ for IP_ADDRESS in `cat $IP_FILE` ; do
    ssh-keyscan $IP_ADDRESS 2>&1 | grep -v "^$" > /dev/null
    [ $? == 0 ] && echo $IP_ADDRESS >> $LOGFILE 2>&1
  done

Just to break this down a little bit more so it's crystal clear what's going on, the ssh-keyscan $IP_ADDRESS 2>&1 will run, any output returned (both stderr & stdout is merged together). All this output is then piped to the grep -v "^$" which will return a 0 for lines that return output (ssh servers running) and a 1 for servers that don't (the "^$" is a blank line).

Quick tangent on loops (for vs. while & how they parse)

The looping mechanism above (for loop) works because the file only contains a string of characters of which none are a space and that each "string" is terminated by a new line character. By default a space is the special separation character that's used to designate to the for loop how to parse the arguments being passed to it. This character is defined by the variable $IFS and can be overridden so that it's the new line character (IFS='^M') for example.

You can make this a little more efficient by replacing the cat $IP_FILE with $( < $IP_FILE ). For example:

$ for IP_ADDRESS in $( < $IP_FILE ) ; do
    ssh-keyscan $IP_ADDRESS 2>&1 | grep -v "^$" > /dev/null
    [ $? == 0 ] && echo $IP_ADDRESS >> $LOGFILE 2>&1
  done

If the lines in the file $IP_FILE included spaces you could either override the $IFS as discussed a moment ago so that it was set to ^M or a while loop could be used instead, i.e. (while read -ra line ; do ... ; done < $IP_FILE).

$ while read -ra IP_ADDRESS ; do
    ssh-keyscan $IP_ADDRESS 2>&1 | grep -v "^$" > /dev/null
    [ $? == 0 ] && echo $IP_ADDRESS >> $LOGFILE 2>&1
  done < $IP_FILE

Your example

touch logfile_$(date "+%Y%m%d%T")
IP_FILE="ip.txt"
LOGFILE="logfile_$(date "+%Y%m%d%T")"


if [[ ! -f ${IP_FILE} ]]; then
 echo "Cannot find IP address!"
 exit 1
fi

for IP_ADDRESS in `cat $IP_FILE` ; do
  #ssh $IP_ADDRESS >> $LOGFILE 2>&1
  ssh-keyscan $IP_ADDRESS 2>&1 | grep -v "^$" > /dev/null
  [ $? == 0 ] && echo $IP_ADDRESS >> $LOGFILE 2>&1
done

Method #2: nmap

You can also do something with the tool nmap.

$ nmap -A -iL ip.txt -p T:22

This will go through the file, ip.txt which can contain hostnames and IP addresses and will scan each one's TCP port # 22, returning results similar to the following:

Nmap scan report for somehost.somedom.local (192.168.1.200)
Host is up (0.012s latency).
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 4.3 (protocol 2.0)
| ssh-hostkey: 1024 2e:32:85:a2:56:23:01:f1:c2:8f:df:aa:83:7a:1e:ad (DSA)
|_2048 f6:a1:23:1d:aa:44:4a:ce:b4:d3:f4:fe:e1:00:47:b7 (RSA)

References

share|improve this answer
    
While running this I get a [: missing `]' error on [ $? == 0] && echo $IP_ADDRESS >> $LOGFILE 2>&1 . any ideas? –  Dolyak Jul 5 '13 at 13:47
    
ok give me one min. Thank you for your help btw. –  Dolyak Jul 5 '13 at 14:04
2  
Why are you using for and cat instead of while and <? –  terdon Jul 5 '13 at 14:08
    
Ok so when I run it i am not receiving out put even though the ips I have in the file (all but one) are valid servers that I can ssh into. –  Dolyak Jul 5 '13 at 14:30
    
@terdon - dunno, I always use for loops - no technical reason. –  slm Jul 5 '13 at 14:31
show 19 more comments

You're looking for the netcat utility (binary executable is called nc). It can perform various network tests, among which a connection-only test to TCP port 22 would also work. If you're using the older netcat utility the command is:

nc -vz [ip.or.hostname] 22 -w [desired.timeout.value.in.seconds]

I believe the updated version gets rid of the -z option by default.

For example:

[jadavis6@cmsoracle ~]$ nc -vz wfwhite.xxx.edu 22 -w 5
nc: connect to wfwhite.xxx.edu port 22 (tcp) timed out: Operation now in progress
[jadavis6@cmsoracle ~]$ echo $?
1
[jadavis6@cmsoracle ~]$ nc -vz ditirlns01.xxx.edu 22 -w 5
Connection to ditirlns01.xxx.edu 22 port [tcp/ssh] succeeded!
[jadavis6@cmsoracle ~]$ echo $?
0
[jadavis6@cmsoracle ~]$
share|improve this answer
    
Nice solution, BTW! –  slm Jul 5 '13 at 13:27
    
That is a GREAT solution but I cant use Netcat on this boxes. –  Dolyak Jul 5 '13 at 13:45
add comment

Someone mentioned netcat, but I'm going to recommend nmap as it is a one of command to do what you want.

nmap -iL path/to/ip_address.txt -p 22

This will give you all the info you need.

share|improve this answer
add comment

If you can't install anything, you should be able to do something like this (adapted from here):

$ for ip in `cat ips.txt`; do 
    ssh -o PreferredAuthentications=publickey foobar@$ip "echo ''" 2>&1 | 
    grep denied >/dev/null && echo "$ip has SSH"; 
  done < ips.txt

The trick here is PreferredAuthentications. This tells ssh to attempt to connect using the key information stored in ~/.ssh. As long as the user foobar does not have access to the remote system (change it to whatever random name you want), the connection will fail with a "Permission denied" error. This means that the grep denied will be successful and therefore the echo command will be run. && means run the next command if the previous one (here, the grep) was successful.

If you run this scriptlet on a file containing the IPs, it will print out only those servers with a running ssh service.

share|improve this answer
    
You might want to add a command to the ssh invocation, otherwise it will try to spawn a terminal session with each server. In the linked example they were doing that by passing $COMMAND to the ssh invocation. –  Joel Davis Jul 5 '13 at 14:34
    
As Joel said, if you do a straight ssh you're opening the connection which is why I was trying to avoid it, by using ssh-keyscan or something else such as nc or nmap. –  slm Jul 5 '13 at 14:37
    
@JoelDavis yes, I was assuming the OP would not have access to simplify the solution. Answer modified. –  terdon Jul 5 '13 at 14:51
    
@terdon - getting rid of the connection is a bit of pain, good idea there. If he can't ssh to the system without a public key, this won't work though, right? –  slm Jul 5 '13 at 14:52
    
@slm I have modified this solution a bit by using a non existent user name, that way you should always get an "Access denied" error from servers that have ssh set up. –  terdon Jul 7 '13 at 14:11
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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