How can I match a pattern over TCP?
I'm trying to write a monitoring script. It should connect to some port on my server, read the output, and if the output is the expected value, print 1 otherwise 0.
I'm working on a solution involving cat < 开发者_C百科/dev/tcp/hostname/port
, but the solution eludes me. Maybe something involving expect? I'd prefer a bash script solution. Help appreciated!
All other solutions use netcat for network support, but you can do away with it if your bash is recent enough and compiled with --enable-net-redirections
(which is, as far as I can tell, all but Debian and Ubuntu; feel free to comment if I should adjust).
Then grep
can do the actual testing. Its return code is a shell one (0 for success, nonzero for failure), so you'd need to invert that, but bash
handles it just fine.
In a nutshell:
< /dev/tcp/host/port grep -q 'expected value'
echo $(( 1 - $? ))
you can use netcat:
echo "GET /"|netcat google.com 80
and then pipe the output to your processing script
#!/bin/bash
EXPECTED="hello"
SERVER="example.com"
PORT="123"
netcat $SERVER $PORT | grep -F -q "$EXPECTED"
if [ $? ]; then
echo 1
else
echo 0
fi
there are little examples here. you can take reference to it. However, you should note that it also depends on what services runs on your port and what protocol it speaks.
if you are connecting to web server, common port is 80. But if you running your own application running as a server, make sure your script knows how to "talk" to each other.
another resource you can look at here. Its gawk though, so if you have gawk, then you may want to try it. (you can "port" to bash too)
I would suggest you use a popen approach. That way you can read with whatever command you like (i.e. nc
) and handle the output iteratively. This can all be spawned by a bash script if necessary.
For example:
#!/usr/bin/env ruby
IO.popen("nc host 4560") do |stdout|
while line = stdout.gets
if line =~ /pattern/
puts "1"
else
puts "0"
end
end
end
Obviously you would need to substitute pattern
with whatever you were looking for. This has the advantage of comparing each line instead of the entire output of the command. I'm not sure which is preferable in your case. I assume from you mentioning expect
that you want a line-by-line approach.
Here is the script in Bash shell which involves HTTP request:
exec {stream}<>/dev/tcp/example.com/80
printf "GET / HTTP/1.1\nHost: example.com\nConnection: close\n\n" >&${stream}
grep Example <&${stream}
[ $? -eq 0 ] && echo Pattern match || echo Pattern not match
See also: More on Using Bash's Built-in /dev/tcp File (TCP/IP).
精彩评论