I have a bash script that is reading a CSV
file , that contains source IP
address , destination IP
address and destination port
.
My script is basically doing 2 tests:
1 Performance
2 Connectivity.
Under performance test, I am copying files from source
to destination
(using scp
) to calculate the the network IO. After that, copying the same file from one location of Destination server to other location on destination server to calculate Disk I/O.
Under connectivity test I am doing nc
from source
to destination
to check whether port
is open or not.
Problem : Sometime while execution of script, it get stuck at some point and then I have to press Ctrl+C
to kill that process to continue the further execution.
Here , i am not able to figure it out why it is getting stuck, and even behavior is not consistent , every time it's stuck at different location in the script.
Please help me in resolving this issue. If required I can post my complete script here.
Update :
Observation : Other thing that i observed , if i don't press Ctrl+C , then script resume automatically after 5 mins.
Part of the actual script , where it is getting stuck.
#Connectivity Test
TMP=$(mktemp)
nc -z -v -n $lastDestinationIP $port >\$TMP
if grep -q "succeeded" <<< cat echo \$TMP;then
echo $x','$lastSourceIP','$lastDestinationIP','$sourceFqdn','$fqdn','$port',Connectivity,NA,NA,NA,Pass,'$(date) | ssh $username@$baseLocation 'cat >> report.txt'
else
echo $x','$lastSourceIP','$lastDestinationIP','$sourceFqdn','$fqdn','$port',Connectivity,NA,NA,NA,Fail,'$(date) | ssh $username@$baseLocation 'cat >> report.txt'
fi
rm $TMP
fi
exit
ENDSSH
Most of the time it stuck while calling exit.
Here is the snippet where it stuck most of the time (from the console).
21 14:48:16 EDT 2014 | ssh puppet-admin@10.X.X.9 'cat >> report.txt','Fri Mar
> fi
>
> #rm KB_33.txt
> #rm MB_10.txt
> #rm MB_100.txt
> rm -rf dummy
> else
> #Connectivity Test
> nc -z -v -n -w 2 10.X.X.17 1524 >/tmp/tmp.GJ1knZF5Jn
> if grep -q "succeeded" <<< cat echo /tmp/tmp.GJ1knZF5Jn;then
21 14:48:16 EDT 2014 | ssh puppet-admin@10.X.X.9 'cat >> report.txt','Fri Mar
> else
21 14:48:16 EDT 2014 | ssh puppet-admin@10.X.X.9 'cat >> report.Fail,'Fri Mar
> fi
> fi
> exit
>
Best Answer
Here's the short and sweet - a
heredoc
is basically a file streamed to a file-descriptor.Most people don't denote the
0<<descriptor
and so you get it on<&0 stdin. ssh
passesstdin
to its invoked process so if you feed it aheredoc
it will pass through the input to the invoked remote shell.The one very special quality about
heredocs
is the difference between a\"'quoted
andunquoted heredoc LIMITER.
So,<<'THIS'
differs from<<THIS.
When you do not quote theLIMITER,
the contents of the here-document are evaluated for${shell:+expansion}
. Once one${shell:+expansion}
pass is completed, there is very little else to distinguish a here-document from any other file fed as<~/input
.For example:
But...
You keep using the
bash <<< herestring
withcat.
I don't know exactly how theherestring
works but I'm willing to betcat's
already involved. Socat
concatenates its<&0stdin
with itsstdout>&1
. That's all it does. So you're unnecessarily complicating<<STDIN
when you<<< cat
it.This can be a real problem if
cat
winds up consuming an input stream which you did not intend it to consume. Run just% cat
at your terminal and it will look like nothing is happening because a terminal'sstdin
andstdout
are the same file - your$(tty)
. But when they differ,cat
combines them anyway and that can get pretty messy if you didn't mean it to happen.It looks to me like some
\'quotes
are skipping an expansion when$(date)
is$expanded
. Then possibly the: null shell builtin
is invoked and|piped
to the next unquoted command afterssh
which would becat >> report.fail
which should generate nothing at all in that file. Socat
is>>appending /dev/null
toreport.fail
, for as long as it can stand it, I guess. Or, more likely, for as long asexit
allowsssh
to carry-on proxying thenull stream.
Also, have you checked to see if you've got a literal
$TMP
in your current working directory? I do seeENDSSH
at the bottom which looks like aheredoc LIMITER
to me so I believe either this is not the entire script or it has been edited by mistake. It would make sense if it were the body of a heredoc to use\$TMP,
but as is I thinknc
will first>truncate
then write itsstdout
to a file named$TMP.
Then again, I guess yourm
it anyway, so maybe you just didn't notice.And because you're
rm
ing$TMP
you may not have realized anyone would be asking this question:How does
$(mktemp)
work for you without thefilename.xxx
argument?UPDATE I looked closer at your output and definitely
>/tmp/tmp.GJ1knZF5Jn
means$(mktemp)
is working - even the\$TMP
part. So you've just taught me that I only need to specifymktemp .xxx
if I specify a filename at all. Thank you.Still I think there is a heredoc at the top somewhere? It could be there is not and
\\
is only an attempt to deal with a side-effect of theecho \$TMP <<<herestring,
but I dunno... Interesting.I don't know if I've got this completely right because I don't know where all of these variables come from. But, this is close to how I would do this:
(which actually renders the last two questions irrelevant anyway)
Note: the
"$quotes"
in the above are forprintf's
benefit on the other side of thessh
process - not for anything else. Those"quotes"
remain as is even after all of the abovePARAMS
are evaluated.There are some things going on up there that I've covered before. For instance the
func() ( scope )
I like to think was covered ok here. The${parameter:-expansion}
was also covered there, but also demonstrated pretty well here and here. I've gotten into some of the weird heredoc stuff here, here, and here. Probably there are others - I guess I like messing up my shell or something.In this case, though, using the function and the heredoc as I have,
cat
can't get stuck.PARAMS
is sent over asstdin
andcat
will quit when it reaches anEOF
(orCTRL-D
) so as soon as it consumesPARAMS
it's going to stop everytime. This is especially important if you are running this in aheredoc
which is also on<&0
becausePARAMS
will stand in the way ofcat
eating your script mid-execute.Anyway, hopefully that helps. If I've missed anything, don't hesitate to ask.