I need to set up a strange system through which an arbitrary command is sent to a number of different servers (well, actually, VPS accounts). We have a command "vpass" that "passes" a command from the root level to resident VPS accounts. Suppose I wanted each VPS to do some trivial thing, like report its hostname. I might use a script like:
So, as you can see, the vpass syntax is:
Now, it would be convenient to set up a little script that runs an arbitrary command that's in a file called "command". To replicate the results above, I create "command" with "hostname" in it, and then do:
That works just right. However, more complex commands fail. For example, this works:
However, putting that exact MySQL command into the "command" file fails. If I add a line "echo $cmd" after the variable assignment, it gives exactly the right command back, yet passing it into the vpass command fails.
Any suggestions on where the failure might come from? I'm at a loss, mainly because of time-induced brain fuzziness. Many thanks in advance.
Update:
I added -x and checked the results... Apparently some strange things are being done to the command:
It seems to my naive troubleshooting that those changes-- the addition of single-quotes throughout the command-- must be the cause of the problem, unless I misunderstand the output of -x.
Update 2:
I don't know why this didn't occur to me before... lack of sleep? Anyway, xargs helps...
So, that works, but I'm a little perturbed that the other method doesn't. If only for my own education, I'd appreciate any thoughts on why that's failing.
Last edited by treesloth; 02-09-2010 at 05:46 PM..
---------- Post updated at 10:36 AM ---------- Previous update was at 10:26 AM ----------
[/COLOR]And I just realized one really brain-dead simple solution: Let the server do the parsing. I do this over ssh sometimes.
This also prevents people from inserting clever things in the 'commands' file that end up running locally.
[rest of the post]
Your method is a little naive in a couple ways. For one thing, it's a useless use of backticks:
Also, your xargs solution could be done with one fewer process like
Basically, whenever you do 'cat foo' you can replace that with a shell redirection in nearly all circumstances. This is quite a bit more efficient.
As for why the command isn't doing what you expect, the shell doesn't substitue strings more than once -- it won't check inside things it substitutes for things like quoted strings or variables. So embedding strings and variables in a string won't work unless you explicitly tell the shell to re-evaluate it, with eval. Note that eval supports all valid syntax so someone could inject variables or local commands where you didn't expect them by escaping $ and so forth.
[COLOR="#738fbf"]
Last edited by Corona688; 02-10-2010 at 01:48 PM..
Thanks for the reply and the excellent pointers. The methods suggested solve a number of problems. I wish it were otherwise, but my scripts probably have plenty of naive errors. I've gotten reasonably good at finding *a* solution to problems, but as I revisit old scripts (well, not really that old... I'm still pretty new at this, as is certainly clear...) I realize that they are far from optimal. I hope to continue discovering that, as that would mean that I'm learning better and better ways.
One general question... If I use the suggested methods:
or
does the shell have to re-read the contents of the "command" file each time, or is that somehow cached? This is a very small file, of course, with negligible read time; however, I suppose there might be cases in which re-reading could have an appreciable effect.
I'd suggest against the xargs method. I'm surprised it worked at all for one thing; I didn't know it was able to swallow quotes like that, and I don't think you can depend on it always doing so the way you expect. Consider what xargs is actuallly for: converting lists into arguments. You're sending it scripts, not lists, which it may cheerfully mangle on the assumption that it can break lists apart wherever it wants.
xargs might run cat a b c d e f. It could also run cat a b c ; cat d e f and not be in error. For cat, the result is the same. But you can't split a script like that and expect it to work!
vpass $account bash < commands on the other hand can swallow and run any valid shell script. You could put quite complex things in commands if you wanted.
As for performance, the shell has to read the file whenever it wants to run it, just like anything else. When you were running 'cat commands' it was reading it from disk too. The operating system will try to keep the entire file in memory if anything uses it, though, which lets the second time its read avoid the disk entirely. The OS will cache almost all disk I/O from any source if it can. (sometimes even when you don't want it to )
Your disk can probably read scripts faster than your computer can run them in any case.
On the remote host it's never cached. That's kind of the point -- you wanted to keep one master copy and not worry about having two dozen copies on your clients. This isn't a problem unless your script's gigantic, your network's very slow, and your connection's very unreliable.
The total disk reads and network traffic is similar to your original method anyway. The lines have to get from disk to A to B one way or another.
Last edited by Corona688; 02-10-2010 at 04:56 PM..
Hi,
As the process of log cleanup, Im using the below command
find $DIR -mtime +3 -type f -exec gzip {} \;
The problem is I want to pass +3 as variable in my unix shell.
I have defined ZPDATE=+3 in my properties file and calling this property file in my script.
If i try the... (6 Replies)
Hi all,
I have a file looks like
AAAA 111
BBBB 222
CCCC 333
need to pass variable value like var1=AAAA and var2=111
to another command for three times with next values.
stuck over here
cat file | while read line
do
export var1=`awk '{print $1}'`
echo $var1
export var2=`cat file... (3 Replies)
I have a script that kicks off several processes in the background and stored their pids in a variable as follows:
PID_DUMP_TRAN=$PID_DUMP_TRAN" "$!
so I then have a list of pids
If I echo $PID_DUMP_TRAN I get back a list of pids e.g. 8210 8211 8212
However I then want to kill all these... (5 Replies)
Hello All,
I am trying to embed variable in sed command to fetch a portion of record between two pattern.
This command is not working ...any suggestion on this how to place the variable in sed command to find a portion .
I am using Sun OS (Solaris).
Thanks
JM (1 Reply)
Hi guys,
I wanted to pass a variable to the sed command which tells which line to be deleted.
a=2;
echo $a;
sed '$ad' c.out
it is throwing an error.
sed: 0602-403 "$a"d is not a recognized function.
I even tried "$a" and \$a.. but it is of no use.
Can you please correct me... (6 Replies)
Hi,
I have a situation where I have to specify a different value to an awk command, I beleive i have the gist of this done, however I am not able to get this correct. Here is what I have so far
echo $id
065859555
This value occurs in a "pipe" delimited file in postition 8. Hence I would... (1 Reply)
hi,
dataParse(){
line="$@"
name="cat /etc/passwd | grep "$line": | cut -f6 -d':'"
eval $name > sam.txt 2>&1
sudo -u $line sed -n 's/data-1/&/p' $name/test.xml >> sam1.txt
}
Here i getting the homedir of the accounts and is set in
name variable.which returns "/home/raju" which i... (3 Replies)
I fairly new to SED. I have tried many different variations of this line of code and even breaking it down into its components and running them separately.
They work individually without variables but when I place the $todbname variable it will either inserts the text "connect to $todbname"... (3 Replies)
Hi,
I am new to unix. Is their a way to pass the output of the line below to a variable var1.
ls -1t | head -1.
I am trying something like var1=ls -1t | head -1, but I get error.
Situation is: I get file everyday through FTP in my unix box. I have to write a script that picks up first... (1 Reply)