Running commands remotely returns unexpected output - bash

I want to kill a process remotely and I use ssh -i command like this:
ssh -i $app_rsa_file_path $app_server_user#$app_server_ip "ps aux | grep java | grep billing | awk '{print $2}' | xargs kill -9 > /dev/null 2>&1"
if I run command directly on the server, it works fine; but in remote version it seems that awk has no effect and the command passes the whole output of ps aux | grep java | grep billing to kill and I get this:
kill: invalid option -- 'D'
Usage:
kill [options] <pid> [...]
Options:
<pid> [...] send signal to every <pid> listed
-<signal>, -s, --signal <signal>
specify the <signal> to be sent
-l, --list=[<signal>] list all signal names, or convert one to a name
-L, --table list all signal names in a nice table
-h, --help display this help and exit
-V, --version output version information and exit
For more details see kill(1).
Any idea about the reason?

you use double-quotes " so you need to escape the $ special character:

Related

How do I get the PID of a command nested within the quotes?

I am trying to get the PID of the command within the quotes (e.g. some-command-here) whilst being able to interact with the process spawned by some-command-here:
x-terminal-emulator -e "some-command-here" &> /dev/null
For example, sometimes apt full-upgrade -y can require user input, thus it is important that the process spawned by some-command-here remain interactive.
x-terminal-emulator -e "some-command-here & echo $! >/tmp/pid" &> /dev/null
cat /tmp/pid
... or get rid of the &>/dev/null:
x-terminal-emulator -e "some-command-here & echo $!"
So, with a bit more testing and research, it seems that this task can be accomplished utilizing ps ax, grep, xargs & cut.
ps ax | grep -v "grep" | grep "sh -c" | grep "some-command-here" | xargs | cut -d ' ' -f 1
🤔How does this work?
When x-terminal-emulator is passed -e it spawns a new shell window and passes it the command within the quotes. In order to execute the command, it passes the new shell the command sh -c along with the quoted command. Thus, sh -c some-command-here. Which is utilized within the searching of the PID above.
ps ax lists the currently running processes.
grep -v "grep" searches the output and removes any processes that contain grep as a process simply because when we launch this query, a process under grep will be created.
grep "sh -c" searches the output for a process that contains sh -c.
grep "some-command-here" searches the output of ps ax for a process that matches what is within the quotes.
xargs converts the output of grep "sh -c some-command-here" into a space delimited list.
cut -d ' ' -f 1 removes the spaces and grabs the first result. Which returns the PID of the process in question.

Different output when running command in bash script vs terminal

When I run the following code in a bash script I receive an output of 2
#!/bin/bash
HIPPO=$(ps -a | grep hippo | wc -l)
echo "$HIPPO"
However when I run the command ps -a | grep hippo | wc -l straight from a command prompt I get an output of 0
Reading the documentation on ps particularly the -a flag, I'm not understanding why the output is different.
How is called your script? If you named it with hippo, it will count in your ps call.
https://superuser.com/questions/935374/difference-between-and-in-shell-script
When you do the command substitution, the command gets runs once according to the above. So I am assuming, the echo is picking a zombie process that ran that command.

Get the PID from the child process

I am having an issue trying to get the PID from a command using Time.
The command I use is:
{ time cp ubuntu/ubuntu-16.04.2-desktop-amd64.iso
ubuntucopia/$i-ubuntu-16.04.2-desktop-amd64.iso; }
2>> "logs/time.log" &
If I use now $!, I've get te PID from TIME. How could I do to get the pid of the command cp? Currently to solve this I am using this:
father=$!
cpPid=$(pgrep -P $father)
With this, not always I get the pid, sometimes $cpPid is empty.
Thank you!
This will get you the pid of the cp command, though you should use a search string more specific than cp, as this sample has a high potential for multiple matches.
ps -eo pid,cmd | grep cp | grep -v grep | awk '{print $1}'

How to access the PID from an lsof.

Given the following command lsof -i:1025 I get:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
ruby 12345 john 11u IPv4 0xb2f4161230e18fd57 0t0 TCP localhost:foobar (LISTEN)
I am trying to write a script to get that PID (12345) and kill it. At the moment I have to run lsof -i:1025, get that PID and then run kill -9 12345.
The lsof(8) man page says:
-t specifies that lsof should produce terse output with process
identifiers only and no header - e.g., so that the output
may be piped to kill(1). -t selects the -w option.
You can use lsof -t -i:1025 | xargs kill -9.
Something like:
#!/bin/bash --
x=`lsof -Fp -i:1025`
kill -9 ${x##p}
Should do it. The 3rd line runs lsof using the -F option to get just the pid, with a leading p. The next line drops the leading p from the output of lsof and uses the result as the pid in a kill command.
Edit: At some point lsof was modified so the file descriptor preceded by an f is always output, whether you ask for it or not (which makes no sense to me, but what do I know). While you could put a | grep '^p' in the back quotes, an easier way is to use the -t option, as noted in fabianopinto's answer below.
man lsof says that you can use -F to specify fields to to be output for processing by other programs. So you can do something like
lsof -i:1025 -Fp | sed 's/^p//' | xargs kill -9
Further to #blm's answer, it didn't work for me exactly because the output of the lsof command was:
p4679
f33
So with the ${x##p} was
4679
f33
The solution
Grab only the first line with | head -n 1:
x=`lsof -Fp -i:"$1" | head -n 1`
kill -9 ${x##p}
And furthermore from #blm's and #Mosh Feu's answers:
lsof -i:1337 -Fp | head -n 1 | sed 's/^p//' | xargs kill
is what ended up doing the trick for me.
I recommend adding this as a bash function and aliasing it
alias kbp='killByPort'
killByPort() {
lsof -i:$1 -Fp | head -n 1 | sed 's/^p//' | xargs kill
}
This shortcut will kill the process quickly for you
kill -9 $(lsof -t -i :3000)
for fish shell users, simply remove the $ sign, so
kill -9 (lsof -t -i :3000)

How do I count specific processes on Mac OS X?

Using a Mac, what would be the best way to count the number of instances of a particular process I am running? This is for a script I am writing to find the number of ffmpeg processes running on my machine.
Should I be using top here? ps aux|grep ffmpeg? What would be the best way to get the number?
grep -c will count occurrences:
count=`ps aux | grep -v "grep" | grep -c ffmpeg`
echo $count
ps aux | grep ffmpeg | wc -l will get you the number of processes that mention the phrase 'ffmpeg' you'll need to minus 1 on this value as ps aux | grep ffmpg is a process also.
You're looking for the program called "wc" -- "wc -l" will count lines for you.
"man wc" for details.
You can try the killall command on the Mac:
$ killall -s ffmpg
kill -TERM 20148
kill -TERM 20146
kill -TERM 20140
The -s means just list what you'd do, but don't actually kill any processes. Pipe it to wc, and you should get your result:
$ killall -s ffmpg | wc -l
3
In a shell script, you can do something like this:
num_of_processes=$(killall -s ffmpg | wc -l)
pgrep:
$ pgrep -c ffmpeg
If you don't use pgrep then mere grep might produce false positives.
To avoid it you could try -C option:
$ ps -C ffmpeg -o pid= | wc -l
Check that your ps version interprets it correctly.

Resources