16

I have two scripts:

  • running_script
  • script_one

I need to get the PID for the/any instances of running_script running under a username, and then pkill to stop the running_script and daughter processes.

We expected something like:

ps -fu will | grep running_script

to find the running_script process(es). However checking the PID against the ps command output show that the cmd as: "bin/bash" for the running_script process.

running_script runs as a detached process(& operator) which starts script_one. I print the PID-s at the start to compare with ps command's output.

running_script  &
echo $! -- $BASHPID

In the real use-case, we won't have PIDs for some running_script processes running. Also, script_one may or may not be a detached process from the running_script parent.

For the purposes of the exercise, script_one just does loops.

while [ true ]
do
    echo "  $0 - 35sec ..."
    sleep 35
done

However that's just the example. The requirement is to get PID for the parent, running_script process(es).

Is there an option on ps or another command that can give me the name of the script file and the PID? Or a method to set a name that can be searched for?

In the final use-case, there could be several instances of running_script so picking them out by name seems the best option to date.

example

I thought it might help to show what the ps command shows, since most responses appear to think that's going to work. I ran this example just a while ago.

$  ./running_script &
$  echo $! - $BASHPID
9047 - 3261
$  ps -ef | grep will

  UID     PID  PPID  C STIME TTY          TIME CMD
  will   8862  2823  0 22:48 ?        00:00:01 gnome-terminal
  will   8868  8862  0 22:48 ?        00:00:00 gnome-pty-helper
  will   8869  8862  0 22:48 pts/4    00:00:00 bash
* will   9047  3261  0 22:55 pts/2    00:00:00 /bin/bash
  will   9049  9047  0 22:55 pts/2    00:00:00 /bin/bash
  will   9059  2886  0 22:56 pts/0    00:00:00 man pgrep
  will   9070  9059  0 22:56 pts/0    00:00:00 pager -s
  will  10228  9049  0 23:31 pts/2    00:00:00 sleep 35
  will  10232  8869  0 23:31 pts/4    00:00:00 ps -ef
  will  10233  8869  0 23:31 pts/4    00:00:00 grep --colour=auto william

I have marked PID #9047, is simply shows: - will 9047 3261 0 22:55 pts/2 00:00:00 /bin/bash

Is there something like a a "jobname" attribute I could set on linux?

will
  • 500
  • Would it be enough to get the PID of the parent process of script1? – terdon Oct 22 '15 at 13:27
  • In the interest of saving some time, every ps option shows "bash/bash", NOT "running_script" when running_script is stared from the command line /terminal. – will Oct 23 '15 at 12:10
  • I'm testing these with v4.3.11(1)-release on linux mint 17. The requirement is for the PID of running_script. There is a (good) compliance reason for that requirement stemming from the hardware and software systems already running. – will Oct 23 '15 at 12:12
  • ps --version --> "procps-ng version 3.3.9" – will Oct 25 '15 at 04:44

4 Answers4

26

Try pgrep -f running_script -- the -f option uses the whole command line to match against, not just the process name

glenn jackman
  • 85,964
6

ps -o pid,args -C bash | awk '/running_script/ { print $1 }'

This uses ps to get the pid and args for all bash processes, then uses awk to print the pid (field 1) of the matching process.

BTW, ps -o pid,args -C bash gives you the pid and the name of the script file you asked for - the script's name is in the args of the bash command.

If you're going to use ps rather than pgrep at least use its full capabilities rather than the extraordinarily ugly ps ... | grep -v grep | grep | awk construct. The last grep isn't even needed as awk can perform the pattern match. In fact, neither of the greps are needed as awk can do it all: ps ax | awk '! /awk/ && /myprocessname/ { print $1}'

cas
  • 78,579
  • The result is a null (or no output), gnu bash: v4.3.11(1)-release. The output of the ps command is: 9047 /bin/bash 9049 /bin/bash, 8869 bash. I suppose PID 8869 is the parent (mother of all) bash processes. May be there's a different result if the running_script command is run from a script or something(??) rather than from the terminal (shell). – will Oct 23 '15 at 12:07
  • What version of ps are you running? Try ps --version. Both ps -ef and ps -o args are supposed to show the full command line, including arguments. And do you have any of the Environment Variables mentioned near the end of man ps set? – cas Oct 23 '15 at 21:52
  • I put version in the question: "procps-ng version 3.3.9". The mint system monitor shows the same information. It probably uses ps (too anyway). However the process pseudo device only shows bash/bash -- Which leads me to believe it is it is bash setting the command information. – will Oct 25 '15 at 04:49
  • yep, you're right. bash changes its args in ps. I'll try to find out if there's a way of getting ps to show the real args. In the meantime, you could try something like this if you are running on linux ps h -o pid -C bash | xargs -IXX grep -sEl 'running_script' /proc/XX/cmdline | sed -re 's:/proc/([^/]*)/.*:\1:' – cas Oct 25 '15 at 05:41
  • FYI, bash only changes its name in ps if you run the script as bash scriptname.sh. If you run it as just ./scriptname.sh (or /path/to/scriptname.sh) then the script's real name will appear in ps – cas Oct 25 '15 at 05:51
  • It also does it if you misuse env as in #!/usr/bin/env bash. Yet another reason why using env like that is broken and why the python crowd should stop recommending it. – cas Oct 25 '15 at 05:58
  • The Env is clean. I may need to resort to writing a tmp file as suggested. BUT that means a file for every process instance ... oy ve! – will Nov 01 '15 at 10:38
  • the PID file idea is a good one, but you should probably use /var/run or /run rather than /tmp. That's what they're for. Otherwise grep it out of /proc/*/cmdline as i suggested above. – cas Nov 01 '15 at 11:05
1
ps -ef | grep -v grep | grep <script_name> | awk '{print $2}'

The above command will give the PID for the script_name. Also you can have the script write a temporary file with its running PID.

To save the current PID, add a line inside the script:

echo $$>/tmp/script_pid.tmp
AdminBee
  • 22,803
  • Maybe you mean ps -ef | grep -v grep | awk '/script_name/ {print $2}'. With pgrep you avoid the nasty grep -v grep – Pablo A May 19 '22 at 04:01
0
#!/bin/bash

# pidofargs.sh
# get process id by first argument of a process
# using `ps -eo pid,args` and `read -a`

# sample use: pidofargs.sh python /usr/bin/youtube-dl

search_grep="$1" # first filter
search_arg1="$2" # second filter

# first filter
ps -eo pid,args | grep "$search_grep" | while read pid args
do
  read -a arg < <(echo "$args")

  # pid    = process id
  # arg[0] = executable file of process
  # arg[1] = first argument of process

  # second filter
  if [[ "${arg[1]}" == "$search_arg1" ]]
  then
    # success
    echo $pid
    break
  fi

done
milahu
  • 208