How to expand variables in bash jobs list - linux

Is it possible to have the variable names in the bash jobs list (jobs command) expanded. E.g. I get job list such as
[1] Angehalten vi $file
[2] Angehalten vi $file
which refer to vi sessions with two different values of $file. Now I want to bring the vi window with a specific file to the front but don't know which job number it has.

You can use jobs -l to get the PID of each, and then look them up in the output of ps, which will show the expanded string:
$ jobs -l
[2]- 6445 Suspended: 18 vi $file
[3]+ 6473 Suspended: 18 vi $file
$ ps | grep vi
6445 ttys000 0:00.03 vi x
6473 ttys000 0:00.03 vi y
6485 ttys000 0:00.00 grep --color vi

Following command should work (tested with bash 4.2.10 on ubuntu 11.10)
paste <(jobs) <(jobs -p | xargs ps -p | tail -n+2 | awk '{print substr($0, index($0, $5))}')
output:
[1] Stopped vi $A vi a
[2]- Stopped vi $A vi b
[3]+ Stopped vi $A vi c
The idea is same as Carl's - extract the command by process id

Similar to Alex's answer but without all the paste and subprocess tricks. It worked for me on FreeBSD 10.0 with bash v4.3.30
jobs -p | xargs ps -p | tail -n+2 | awk '{print substr($0, index($0, $5))}'

If you can try and expand the variables before you execute the command.
Maybe there is a way of doing this without ever writing to file.
If not use mktemp to start the temp file.
cmd1=sleep
echo "$cmd1 10 &" > /tmp/veryscary.sh && source /tmp/veryscary.sh

jobs -p | while read pid; do ps auxwq $pid; done | grep -v USER

Further to arj's answer but without the need for a temp file, how about:
cmd1=sleep
eval `echo "$cmd1 10 &"`

Related

Display the name of all running processes in Linux in a file using a bash script

I need to display the name of all running processes in Linux in a file using a bash script. I wrote the code, but didnt succeed:
#!/bin/bash
for i in `ps aux| awk '{print $5}'`;
echo $i > /tmp/test;
done
Need your assistance, Thanks.
Using the for, the syntax is slightly different:
#!/bin/sh
cat /dev/null > /tmp/test
for i in $(ps aux | awk '{print $5}'); do
echo $i >> /tmp/test;
done
You missed the do operator
The output redirector > on a loop should change to appending >>, otherwise only the last value of the loop will be saved.
But as #stark said, the for is not required:
#!/bin/sh
ps aux | awk '{print $5}' > /tmp/test;
I'm not sure, what your output should look like. With your template, and the fixes from Glauco Leme, I only got the VSZ of all the processes.
I assume you need the cmd of each process, then you just can use ps -e --no-headers --format cmd.
In case you need it in a file:
ps -e --no-headers --format cmd > /tmp/test
I hope this will do what you need.

Problems with accessing job PID in LINUX shellscript

if I run the expression
ps -fu $USER| grep 'mount' | grep -v 'grep' | awk '{print $2}'
in the command line, I get - as expected - the PID of the processes containing "mount" in their description.
I want to achieve the following to kill certain background processes programmatically. The following code in the shell script:
#!/usr/bin/env bash
mountcmd="ps -fu $USER| grep 'mount' | grep -v 'grep' | awk '{print $2}' "
mountpid=$(eval "$mountcmd")
echo "Found existing background job PID: " "$mountpid"
does not provide the PID, but the output of echo is:
Found existing background job PID: wgeithne 6284 1 0 17:09 pts/3 00:00:00 minikube mount /u/wgeithne/bin/grafana/config:/grafana
How do I get the only the PID as output of my script?
The stupid eval trick requires additional escaping of the dollar sign in the Awk script. But really, a massively superior solution is to avoid stupid eval tricks.
Perhaps see also https://mywiki.wooledge.org/BashFAQ/050
If you really need to reinvent pidof, probably get rid of the antipatterns.
mountpids=$(ps -fu "$USER" | awk '/[m]ount/ { print $2 }')

Need to run ksh script in windows korn shell

I am new to korn shell, I am trying to run ksh script that to kill all 3 days older process in my server, that works good for direct input, but when I put this in a for look script I got error, someone please help.
FYI, korn shell is installed in windows server.
> cat test.ksh
#! /usr/bin/ksh
for i in {ps -eo etime,pid,args | awk -F- '$1>3{print}' | grep -i read_ini | awk '{print $2}'}
do
kill -9 $i
done
LCQU#SETOPLCORA01Q [/dev/fs/E/home/serora]
> ./test.ksh
./test.ksh[3]: syntax error: `|' unexpected
LCQU#SETOPLCORA01Q [/dev/fs/E/home/serora]
> ksh test.ksh
test.ksh[3]: syntax error: `|' unexpected
LCQU#SETOPLCORA01Q [/dev/fs/E/home/serora]
> ls -l test.ksh
-rwxrwx--- 1 jagadee Domain Users 133 Dec 24 13:16 test.ksh
Do not use {} but $() for a subprocess:
for i in $(ps -eo etime,pid,args | awk -F- '$1>3{print}' | grep -i read_ini | awk '{print $2}')
do
kill -9 $i
done

Why part of the script cannot execute in the crontab

I have a script stopping the application and zipping some files:
/home/myname/project/stopWithZip.sh
With the properties below:
-rwxrwxr-x. 1 myname myname778 Jun 25 13:48 stopWithZip.sh
Here is the content of the script:
ps -ef | grep project | grep -v grep | awk '{print $2}' |xargs kill -15
month=`date +%m`
year=`date +%Y`
fixLogs=~/project/log/fix/$year$month/*.log.*
errorLogs=~/project/log/error/$year$month/log.*
for log in $fixLogs
do
if [ ! -f "$log.gz" ];
then
gzip $log
echo "Archived:"$log
else
echo "skipping" $log
fi
done
echo "Archived fix log files done"
for log in $errorLogs
do
if [ ! -f "$log.gz" ]; then
gzip $log
echo "Archived:"$log
else
echo "skipping" $log
fi
done
echo "Archived errorlog files done"
The problem is except this ps -ef | grep project | grep -v grep | awk '{print $2}' |xargs kill -15 command, other gzip commands are not executed. I totally don't understand why.
I cannot see any compression of the logs in the directory.
BTW, when I execute the stopWithZip.sh explicitly in command line, it works perfectly fine.
In crontab:
00 05 * * 2-6 /home/myname/project/stopWithZip.sh >> /home/myname/project/cronlog/$(date +"\%F")-stop.log 2>&1 (NOT work)
In command line:
/home/myname/project>./stopWithZip.sh (work)
Please help
The script fails when run under cron because your script is invoked with project in its path, so the kill pipeline kills the script too.
You could prove (or disprove) this by adding some tracing. Log the output of ps and of awk to log files:
ps -ef |
tee /tmp/ps.log.$$ |
grep project |
grep -v grep |
awk '{print $2}' |
tee /tmp/awk.log.$$ |
xargs kill -15
Review the logs and see that your script is one of the processes being killed.
The crontab entry contains:
/home/myname/project/stopWithZip.sh >> /home/myname/project/cronlog/$(date +"\%F")-stop.log 2>&1
When ps lists that, it contains 'project' and does not contain 'grep' so the kill in the script kills the script itself.
When you run it from the command line (using a conventional '$' as the prompt), you run:
$ ./stopWithZip.sh
and when ps lists that, it does not contain 'project' so it is not killed.
If you ran:
$ /home/myname/project/stopWithZip.sh >> /home/myname/project/cronlog/$(date +"\%F")-stop.log 2>&1
from the command line, like you do with cron (crontab), you would find it fails.

How to check which program runs inside gnome-terminal

I want to write a program which prints the current focused window name and if it is a gnome-terminal, then prints out the running program inside the current gnome-terminal tab (for example vim, if a vim session is running).
To get the currently focused window name, I used:
xprop -root | grep "_NET_ACTIVE_WINDOW(WINDOW)"
xprop -id 0x220ad5a | grep "WM_CLASS(STRING)"
If the current window is a gnome-terminal, this will return 'gnome-terminal'.
But how can I find out the program running inside gnome-terminal (more precisely: inside the current gnome-terminal tab)? I thought about using dbus but gnome-terminal does not seem to support it.
I needed to solve the same problem and after some investigation I discovered
that wmctrl and pstree prints processes in the same order.
DISCLAIMER: I'm not sure this is always the case but in my case where I use this method to open up a "cheatsheet" for manual review a problem with it would be detected immediately and so for had no problem.
Here is a demo-script that when run will output the correct row of the pstree that corresponds to the currently active terminal window. For debugging it prints intermediate steps into ~/debug.txt
#!/bin/bash
winid=$(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW)/ {print $NF}' | xargs printf "%#010x\n")
echo 'winid:'$winid >> ~/debug.txt
winclass=$(xprop -id $winid | awk '/WM_CLASS/ {print $NF}')
niceclass=${winclass//\"/}
echo 'winclass:'$niceclass >> ~/debug.txt
if [ $niceclass == "Gnome-terminal" ]
then
terminalPID=$(xprop -id $winid | awk '/_NET_WM_PID/ {print $NF}')
echo 'winPID:'$terminalPID >> ~/debug.txt
# get inx of window for this PID
termInx=$(wmctrl -l -p | grep $terminalPID | awk '/'"$winid"'/ {print NR}')
echo 'term inx:'$termInx >> ~/debug.txt
# Take the childprocess of that inx and PID
shell_process=$(pstree -p $terminalPID | sed "s/.*(1998)//" | sed "s/\W*//" | awk 'NR=='$termInx)
pstree -p $terminalPID >> ~/debug.txt
echo 'found process:'$shell_process >> ~/debug.txt
echo 'found process:'$shell_process
fi
Expected output:
tony#tony-mini:~$ ./test_so.sh
found process:bash(8001)---test_so.sh(9869)---test_so.sh(9885)-+-awk(9889)
Then pick out the desired child.
Get the gnome terminal PID, and check which processes have this number as PPID.
I have answered a very similar question few days ago, see this link for details.
Thanks Adam! I am almost there. With xprop I can get the PID of the gnome-terminal (6736). But unfortunately, there is only one process for all gnome-terminal windows and tabs. See this pstree output with two opened gnome-terminal windows:
-gnome-terminal(6736)-+-bash(6738)---vim(6780)
| |-bash(7026)---pstree(7045)
| | `-{gnome-terminal}(6740)
Is there a way to find out the bash pid of the currently opened gnome-terminal tab?

Resources