This question already has an answer here:
Bash command substitution on remote host [duplicate]
(1 answer)
Closed 3 years ago.
I want to kill process. Without kill cmd it works fine. But with kill cmd i get:
grep: invalid option -- 'S'
Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.
awk: cmd. line:1: {print
awk: cmd. line:1: ^ unexpected newline or end of string
kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
Doesn't work:
ssh someUser#someHost kill $(ps -aux | grep 'screen -S cats' | awk '{print $2}')
Works fine:
ssh someUser#someHost ps -aux | grep 'screen -S cats' | awk '{print $2}'
The command substitution runs ps locally, to produce the argument for the remote kill command.
To make the command substitution run remotely, quote the entire string (which is a good idea; you generally don't want ssh having to figure out how to join its arguments into a single command).
# Using $'...', which may contain escaped single quotes
ssh someUser#someHost $'kill $(ps -aux | awk \'/screen -S cats/ {print $2}\''
or
# Using standard double quotes, but making the user responsible
# for escaping any dollar signs that need to be passed literally.
ssh someUser#someHost "kill \$(ps -aux | awk '/screen -S cats/ {print \$2}'"
Related
When trying to run the following command over ssh:
ssh hostname 'for pid in $(ps -ef | grep "some process" | awk '{print $2}'); do kill -9 $pid; done'
I get the following error:
awk: cmd. line:1: {print
awk: cmd. line:1: ^ unexpected newline or end of string
I've tried escaping in different ways but haven't found the correct way - or maybe it's something else?
Thanks in advance!
You cannot include single quotes into a single-quoted string, since nothing is interpreted inside, except the single quote that closes the string. You can concatenate the single-quoted strings with "'":
ssh host 'for pid in $(ps -ef | grep "some process" | awk '"'"'{print $2}'"'"'); do kill -9 $pid; done'
Alternatively, concatenate escaped single quotes (\'):
ssh host 'for pid in $(ps -ef | grep "some process" | awk '\''{print $2}'\''); do kill -9 $pid; done'
See Strong Quoting.
The Cause of the Error
Your command is interpreted as a couple of $IFS-separated arguments:
for pid in $(ps -ef | grep "some process" | awk {print
}); do kill -9 $pid; done
There is no $2 in the strings, since $2 is interpreted as a shell variable, and the value of this variable in the normal shell context is empty.
Thus, you have sent the following command to the server:
for pid in $(ps -ef | grep "some process" | awk {print }); do kill -9 $pid; done
If you run this command in a terminal, you will get the same error from AWK.
This question already has answers here:
Execute a command on remote hosts via ssh from inside a bash script
(4 answers)
Closed 7 years ago.
I need a help with a bash script that connect to server as root, execute some commands and then exit from the server.
I tried this script but when login login to server performed the command not running !
#!/bin/bash
sudo ssh -o ConnectTimeout=10 $1 'exit'
if [ $? != 0 ]; then
echo "Could not connect to $1 , script stopped"
exit
fi
sudo ssh $1
echo "SRV=`cat /etc/puppet/puppet.conf | grep -i srv_domain | awk '{print $3}'`"
echo $SRV
echo "puppetMaster=`host -t srv _x-puppet._tcp.$SRV | head -1 | awk '{print $8}' | cut -f1 -d"."`"
echo $puppetMaster
'exit'
I'm surprised nobody has suggested a heredoc yet.
sudo ssh "$1" <<'EOF'
SRV=`cat /etc/puppet/puppet.conf | grep -i srv_domain | awk '{print $3}'`
echo $SRV
echo "puppetMaster=`host -t srv _x-puppet._tcp.$SRV | head -1 | awk '{print $8}' | cut -f1 -d"."`"
echo $puppetMaster
EOF
This feeds everything from the <<'EOF' until the line starting with EOF into the stdin of ssh, to be received and run by the remote shell.
The commands following ssh machine in a script are not run on the machine. They will be run on the local machine once the ssh exits.
Either specify the commands to run as an argument of ssh, or alternatively, run ssh and make it read the commands from standard input, and send the commands to it.
ssh machine ls
# or
echo ls | ssh machine
You seem to be a little confused as to what runs where.
ssh -o ConnectTimeout=10 $1 'exit'
will connect to $1, run exit, and disconnect.
ssh -o ConnectTimeout=10 $1 'echo hello world'
will print hello world on
the server and then disconnect.
ssh $1
will open up a shell on the remote. After the shell has ended, the following commands will run locally.
echo "SRV=`cat /etc/puppet/puppet.conf | grep -i srv_domain | awk '{print $3}'`"
echo $SRV
echo "puppetMaster=`host -t srv _x-puppet._tcp.$SRV | head -1 | awk '{print $8}' | cut -f1 -d"."`"
echo $puppetMaster
'exit'
What you probably want is start bash on the remote and forward to it the commands you want to give it via stdin.
echo "my commands" | ssh $1 bash
Technically, you don't need that bash -- ssh will start bash even without it (but with different rc files).
I have syntax error near unexpected token & in next :
in bash scripts its'go like this :
#!/bin/bash
var1=`(/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null)|& grep real|awk '{print $2}'`
when i issue this command on cli i get good output, problem is when invoke this in script i can get any output from var1
./check_cdifonline.sh: command substitution: line 2: syntax error near unexpected token `&'
./check_cdifonline.sh: command substitution: line 2: `(/usr/bin/time cdifonline -CD 186821 -ALL >/dev/null) | & grep real | awk '{print $2}''
You can use the sequence |& to pipe both stdout and stderr from one process to another.
You cannot have a space between the | and the &. (csh and tcsh allow a space; bash does not.) I suspect you happen to be typing it without the space when you run the command interactively; the syntax is the same either way.
This:
foo |& bar
is shorthand for this:
foo 2>&1 | bar
UPDATE :
With bash 3.2.25, the |& token is not recognized; was added as a new feature in bash 4.1. Running your script with the older bash, I get the same error message you do.
To make your script compatible with older versions of bash, just do the equivalent redirection without using the |& operator:
#!/bin/bash
var1=`(/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null) 2>&1 | grep real | awk '{print $2}'`
Further refinements: Use $(...) rather than `...`:
#!/bin/bash
var1=$((/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null) 2>&1 | grep real | awk '{print $2}')
You can also incorporate the grep search into the awk command:
#!/bin/bash
var1=$((/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null) 2>&1 | awk '/real/ {print $2}')
Warning: I have not thoroughly tested these beyond verifying that they run without syntax errors.
I still see no difference between |& and | &. Is it possible that /bin/bash is a different version than what you're running interactively? Try /bin/bash --version and echo $BASH_VERSION.
Try change to:
var1=$(/usr/bin/time cdifonline -CD 186821 -ALL >/dev/null | awk '/real/ {print $2}')
Thanks Keith I have no problems anymore you saved my day :) so the bash version was the problem and with avoiding of & I have no errors, thanks also for fine tuning :)
so this works with my bash version
#!/bin/bash
var1=`(/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null) 2>&1 | grep real | awk '{print $2}'`
Okay so here's another one about the StarMade server.
Previously I had this script for detecting a crash, it would simply search through the logs:
#!/bin/bash
cd "$(dirname "$0")"
if ( grep "[SERVER] SERVER SHUTDOWN" log.txt.0); then
sleep 7; kill -9 $(ps -aef | grep -v grep | grep 'StarMade.jar' | awk '{print $2}')
fi
It would find "[SERVER] SERVER SHUTDOWN" and kill the process after that, however this is not a waterproof method, because with different errors it could be possible that the message doesn't appear, rendering this script useless.
So I have this tool that can send commands to the server, but returns an EOF exception when the server is in a crashed state. I basically want to grab the output of this command, and use it in the if-statement above, instead of the current grep command, in such a way that it would execute the commands below when the grep finds "java.io.EOFException".
I could make it write the output to a file and then grep it from there, but I wonder, isn't there a better/more efficient method to do this?
EDIT: okay, so after a bit of searching I put together the following:
if ( java -jar /home/starmade/StarMade/StarNet.jar xxxxx xxxxx /chat) 2>&1 > /dev/null |grep java.io.EOFException);
Would this be a valid if-statement? I need it to match "java.io.EOFException" in the output of the first command, and if it matches, to execute something with "then" (got that part working).
Not sure to solve your problem, but this line:
ps -aef | grep -v grep | grep 'StarMade.jar' | awk '{print $2}'
could be change to
ps -aef | awk '/[S]tarMade.jar/ {print $2}'
The [S] prevents awk from finding itself.
Or just like this to get the pid
pidof StarMade.jar
I need to implement a shell script that kills a process. The problem is that I need to do a conditional to be able to see if the process is running or not.
This is my code, but it is not working:
#!/bin/sh
if [ -x "MY_PROCCESS_NAME"]; then
killall MY_PROCCESS_NAME
else
echo "Doesn't exist"
fi
This is the error:
line 3: [: missing `]'
to check if a process is running on mac os x you can use:
pid=$(ps -fe | grep 'process name' | grep -v grep | awk '{print $2}')
if you want to reduce the number of shell scripts you can enclose one of the characters of the name of the process in square brackets:
pid=$(ps -fe | grep '[p]rocess name' | awk '{print $2}')
combined in your test this would look like:
pid=$(ps -fe | grep '[p]rocess name' | awk '{print $2}')
if [[ -n $pid ]]; then
kill $pid
else
echo "Does not exist"
fi
it's a little more complicated than you would need to do under linux as you generally have the 'pgrep' command, which is the rough equivalent of the 'ps -fe | grep ... | grep -v grep'
not sure if it would work in OSX, it works in ubuntu.
but as a one liner:
ps aux | awk '$11~/vim/ {PID = $2} END {if (PID) print "kill -9 "PID; else print "echo no process"}' | bash
what it does is it finds a process, in this case, vim and returns the kill -9 pid if no string is found it returns echo no process it then pipes the output to bash.