How can use one ssh for two commands to save 2 different files - linux

How can use one ssh for two commands to save 2 different files. Like one command is ps -ef | grep Consumer | cut -f6 -d' ' and save this output in file.log, second command is ps -ef | grep Test | cut -f7 -d' ' and save output in test.log

Only ps -ef needs to be run on the remote system. Parsing the output can happen at local system.
& It's easier with awk. Needs just single ssh session & ps -ef command snapshot:
ssh user#host ps -ef | awk -F' ' '/Consumer/{print $6 > "file.log"}; /Test/{print $7 > "test.log"}'
grep+cut can happen within awk - '/pattern/{print $n}'
File redirection can also happen easily with awk. Check the syntax in above answer.

I would rather prefer to do parsing on remote system only as ps -ef gives a big output and if we don't parse and cut it over there then entire output is transferred from remote system to local system over network. It can take more time if output size increases. And we don't even need entire output on local system too so it is better parse it on remote system only.
ssh user#host ps -ef | grep Consumer | cut -f6 -d' ' > file.log; ps -ef | grep Test | cut -f7 -d' ' > test.log

Related

Capture pid of a process started from a terminal with its unique command line

I'm trying to get the process id of multiple processes run from a multiple tmux windows. Each processes started have their unique command line. I think only the command line is unique as there can be multiple processes with same name. what i did currently is
process_pid=$(ps --no-headers aux | grep "${process_cmd_line}" | grep -v grep | awk '{print $2}' | tr '\n' '')
This works for me. But i want to know if this is the correct approach to do this. I know there are output format specifiers. Any example to do the same with the format specifier or an improvement over the code above?

How to turn off auto add escape character feature in Linux

I am trying to pass a command to a remote server using ssh. while my commands have some characters like ", $, ', \ which often requires a backslash as a escape character except ' (single quote), but the system is automatically taking an escape character \ before the single codes while execution. Can some one help me how to turn off this.
OS : RHEL
my Code :
ssh -q $server "ps -ef | grep mongo | grep conf | awk '{print \$(NF-2)}'
While execution, the code becomes
ssh -q $server "ps -ef | grep mongo | grep conf | awk \'{print $(NF-2)}\'"
I need to turn off this feature
Your analysis isn't really correct. Anyhow, there is no particular reason to run Awk remotely, or grep at all here (because Awk does all of that nicely and efficiently with a very minor refactoring):
ssh -q "$server" ps -ef |
# This runs locally instead
awk '/mongo/ && /conf/ {print $(NF-2)}'

grep a variable containing special characters

i'm new to bash scripting and i have to determine if a process is running in a linux environment.
Actually i use the follow command to do the job:
#ps -ef | awk '{print substr($0, index($0,$8))}' | grep -v grep | grep -w -F $PROCESSNAME
where
awk '{print substr($0, index($0,$8))}'
allow me to ignore UID PID PPID C STIME TTY TIME fields and
grep -v grep
allow me to ignore the row that contains the command itself. So at this point i have a list of all processes running on the system.
Finally:
grep -w -F $PROCESSNAME
read a variable which contains the name of the process that i want to check.
For what i understand the full command should return only the row that has the exact value of $PROCESSNAME
Actually this doesn't works correctly for processes that follow the pattern "[processname]", and probably also for other patterns.
For example to simplify, if i have a running process named "[vmmemctl]" and i run:
#ps -ef | grep -v grep | grep -w -F "vmmemctl]"
it actually returns a result:
#root 615 2 0 Feb26 ? 00:01:00 [vmmemctl]
but the actual process name in the command is different from the process name in the result.
What is the correct command that doesn't have this behavior?
Thank you
awk to the rescue!
ps -ef | awk '$8=="[command]"{NF=8;print}'
or
ps -ef | awk -v c="vmmemctl]" '$8==c{NF=8;print}'
note that this is for an exact match not pattern.
since this is an exact match the command can have spaces and other special chars in it (it's not pattern match but string equality). Using your variable name it will look like this
ps -ef | awk -v c="$PROCESSNAME" '$8==c{NF=8;print}'

Create a list of process ordered by status

I need create a shell script to list the process by status type.
The output must be something like:
Process running:
[process]
Process sleeping:
[process]
ETC
I did this, but doesnt work the ps aux | awk '$8 ~ PROCESS':
for PROCESS in `ps -v | awk 'NR!=1 {print $2}' | sort -u`; do
echo "Procesos como $PROCESS:"
ps aux | awk '$8 ~ PROCESS'
done
Cause that script outputs all the process, not filter by Process.
Any help?
A simple solution would be to use ps and sort:
ps u | sort -rk 8
-r reverses the sort (so that the list header remains above), and -k 8 selects the 8th field (STAT).
You can then select processes in a specific state using anything form head to awk, and print out whatever you like.
You can also use top, in non-interactive mode ( the -S option to display and sort by state):
top -b -n 1 -S

How to specify more spaces for the delimiter using cut?

Is there any way to specify a field delimiter for more spaces with the cut command? (like " "+) ?
For example: In the following string, I like to reach value '3744', what field delimiter I should say?
$ps axu | grep jboss
jboss 2574 0.0 0.0 3744 1092 ? S Aug17 0:00 /bin/sh /usr/java/jboss/bin/run.sh -c example.com -b 0.0.0.0
cut -d' ' is not what I want, for it's only for one single space.
awk is not what I am looking for either, but how to do with 'cut'?
thanks.
Actually awk is exactly the tool you should be looking into:
ps axu | grep '[j]boss' | awk '{print $5}'
or you can ditch the grep altogether since awk knows about regular expressions:
ps axu | awk '/[j]boss/ {print $5}'
But if, for some bizarre reason, you really can't use awk, there are other simpler things you can do, like collapse all whitespace to a single space first:
ps axu | grep '[j]boss' | sed 's/\s\s*/ /g' | cut -d' ' -f5
That grep trick, by the way, is a neat way to only get the jboss processes and not the grep jboss one (ditto for the awk variant as well).
The grep process will have a literal grep [j]boss in its process command so will not be caught by the grep itself, which is looking for the character class [j] followed by boss.
This is a nifty way to avoid the | grep xyz | grep -v grep paradigm that some people use.
awk version is probably the best way to go, but you can also use cut if you firstly squeeze the repeats with tr:
ps axu | grep jbos[s] | tr -s ' ' | cut -d' ' -f5
# ^^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^
# | | |
# | | get 5th field
# | |
# | squeeze spaces
# |
# avoid grep itself to appear in the list
I like to use the tr -s command for this
ps aux | tr -s [:blank:] | cut -d' ' -f3
This squeezes all white spaces down to 1 space. This way telling cut to use a space as a delimiter is honored as expected.
I am going to nominate tr -s [:blank:] as the best answer.
Why do we want to use cut? It has the magic command that says "we want the third field and every field after it, omitting the first two fields"
cat log | tr -s [:blank:] |cut -d' ' -f 3-
I do not believe there is an equivalent command for awk or perl split where we do not know how many fields there will be, ie out put the 3rd field through field X.
Shorter/simpler solution: use cuts (cut on steroids I wrote)
ps axu | grep '[j]boss' | cuts 4
Note that cuts field indexes are zero-based so 5th field is specified as 4
http://arielf.github.io/cuts/
And even shorter (not using cut at all) is:
pgrep jboss
One way around this is to go:
$ps axu | grep jboss | sed 's/\s\+/ /g' | cut -d' ' -f3
to replace multiple consecutive spaces with a single one.
Personally, I tend to use awk for jobs like this. For example:
ps axu| grep jboss | grep -v grep | awk '{print $5}'
As an alternative, there is always perl:
ps aux | perl -lane 'print $F[3]'
Or, if you want to get all fields starting at field #3 (as stated in one of the answers above):
ps aux | perl -lane 'print #F[3 .. scalar #F]'
If you want to pick columns from a ps output, any reason to not use -o?
e.g.
ps ax -o pid,vsz
ps ax -o pid,cmd
Minimum column width allocated, no padding, only single space field separator.
ps ax --no-headers -o pid:1,vsz:1,cmd
3443 24600 -bash
8419 0 [xfsalloc]
8420 0 [xfs_mru_cache]
8602 489316 /usr/sbin/apache2 -k start
12821 497240 /usr/sbin/apache2 -k start
12824 497132 /usr/sbin/apache2 -k start
Pid and vsz given 10 char width, 1 space field separator.
ps ax --no-headers -o pid:10,vsz:10,cmd
3443 24600 -bash
8419 0 [xfsalloc]
8420 0 [xfs_mru_cache]
8602 489316 /usr/sbin/apache2 -k start
12821 497240 /usr/sbin/apache2 -k start
12824 497132 /usr/sbin/apache2 -k start
Used in a script:-
oldpid=12824
echo "PID: ${oldpid}"
echo "Command: $(ps -ho cmd ${oldpid})"
Another way if you must use cut command
ps axu | grep [j]boss |awk '$1=$1'|cut -d' ' -f5
In Solaris, replace awk with nawk or /usr/xpg4/bin/awk
I still like the way Perl handles fields with white space.
First field is $F[0].
$ ps axu | grep dbus | perl -lane 'print $F[4]'
My approach is to store the PID to a file in /tmp, and to find the right process using the -S option for ssh. That might be a misuse but works for me.
#!/bin/bash
TARGET_REDIS=${1:-redis.someserver.com}
PROXY="proxy.somewhere.com"
LOCAL_PORT=${2:-6379}
if [ "$1" == "stop" ] ; then
kill `cat /tmp/sshTunel${LOCAL_PORT}-pid`
exit
fi
set -x
ssh -f -i ~/.ssh/aws.pem centos#$PROXY -L $LOCAL_PORT:$TARGET_REDIS:6379 -N -S /tmp/sshTunel$LOCAL_PORT ## AWS DocService dev, DNS alias
# SSH_PID=$! ## Only works with &
SSH_PID=`ps aux | grep sshTunel${LOCAL_PORT} | grep -v grep | awk '{print $2}'`
echo $SSH_PID > /tmp/sshTunel${LOCAL_PORT}-pid
Better approach might be to query for the SSH_PID right before killing it, since the file might be stale and it would kill a wrong process.

Resources