Today I was trying to write a convenience wrapper script that ran commands remotely on a server (for one of the people we work with). But, for some reason, ssh handles arguments in a completely suprising (and annoyingly inconvenient) manner that completely ignores quotes.
For example:
timcharper@timcharper:~ $ ssh my_server grep "4 5 6" ./ grep: 5: No such file or directory grep: 6: No such file or directory
Grrr…. this made me feel ANGRY. Because of this, I couldn’t use the “$@” trick to splat all the arguments on the end and just move on with life. But it’s cool, because I’ve got a thick table to bang my head against, combined with an overly-aggressive problem-solving drive that won’t accept no for an answer.
So, I came across an awk trick to escape every character in a string, and another trick to iterate over arguments. Combining the two techniques did the trick, and I can now properly pass command line arguments through an ssh wrapper script. Since it depends on bash and awk, and bash and awk are on EVERY POSIX system out there, it’s a winner.
#!/bin/sh
CMD=""
for (( i = 1; i <= $# ; i++ )); do
eval ARG=\$$i
CMD="$CMD $(echo "$ARG" | awk '{gsub(".", "\\\\&");print}')"
done
ssh my_server cd /path/to/app \&\& RAILS_ENV=production $CMD
Surprisingly, this is quite bullet broof, and properly escapes strings and preserves arguments like:
./remote.sh grep "hello there" . -R ./remote.sh grep "So I says to the typewriter, \"Hey, I'm in quotes\"" . -R ./remote.sh grep "\"" . -R
I wish somebody had posted a solution like this for me to find, so, here you go. If you came here looking for this solution, I probably saved you an hour of your life, and a lot of stress to boot. You’re welcome.
Have you ever wasted more than an hour on a trivial problem like this? Is there an easier way to do this?
Subscribe to Post Comments [Atom]
March 2008 April 2008 May 2008 June 2008 July 2008 August 2008 October 2008 November 2008 February 2009 June 2009 December 2009 January 2010 February 2010 May 2010 June 2010 November 2010
Subscribe to Posts [Atom]