5

I have written a script where i need to pass several arguments with the same script, the script is being executed after a certain time using cron. In order to make sure that there are no multiple instances of the scripts running, i've made a check to check if the process of the script is running using ps -ef | grep -v grep | grep Connection_Manager.sh

I want to check which arguments are being used in the running process of the script when i perform a check using ps -ef. How can i check the arguments which are being used in the running process of the script?

4 Answers 4

15

With respect to checking if the process is already running I'd change what you're doing slightly and use pgrep instead.

$ pgrep -f Connection_Manager.sh

Example

$ pgrep -f Connection_Manager.sh
16293

The -f switch allows pgrep to match the entire command line and not just the first part.

Command line arguments

For this you have a couple of methods. You could try parsing them from the output of pgrep as well. You'll need to add an additional switch, -a.

Example

$ pgrep -af Conn
17306 /bin/bash ./Connection_Manager.sh arg1 arg2

Then use awk, sed or something similar to parse their output.

sed

$ pgrep -af ./Conn | sed 's/.*Connection_Manager.sh //'
arg1 arg2

awk

$ pgrep -af ./Conn | tr '\000' ' '| awk '{print $4, $5}'
arg1 arg2

These 2 methods are off the top of my head, they could no doubt be streamlined.

Using /proc/

But depending on the number of arguments and the length this could cause you issues if the command line is overly long in length. So I'd probably go with the second method and parse the contents of the process's cmdline file. Every process has a set of files within Linux' /proc filesystem that contains meta information about that process.

$ ls /proc/19146 
attr        cmdline          environ  limits     mountinfo   numa_maps      personality  stack    task
autogroup   comm             exe      loginuid   mounts      oom_adj        root         stat     timers
auxv        coredump_filter  fd       map_files  mountstats  oom_score      sched        statm    wchan
cgroup      cpuset           fdinfo   maps       net         oom_score_adj  sessionid    status
clear_refs  cwd              io       mem        ns          pagemap        smaps        syscall

One of these files is the file cmdline. But you have to pay special attention to the contents of this file. The arguments within this file are separated by NUL characters. You can use cat -v <file> to see them in a terminal window.

$ cat -v cmdline 
/bin/bash^@./Connection_Manager.sh^@arg1^@arg2^@

This substitutes ^@ in place of the NUL's.

So parsing the contents can be done in a variety of ways, one method is discussed in @Joesph's answer, using xargs -0 .... Another is using cat -v.

Examples

xargs

$ xargs -0 < cmdline 
/bin/bash ./Connection_Manager.sh arg1 arg2

cat

$ cat -v cmdline 
/bin/bash^@./Connection_Manager.sh^@arg1^@arg2^@

You can use sed to cleanup this 2nd method a bit.

$ cat -v cmdline | sed 's/\^@/ /g'

References

1
  • Thanks a lot for the detailed and variety of ways to handle multiple instances. Dec 28, 2013 at 12:42
2

If you're on a GNU/Linux system with access to a proc file system, here's how I would do it:

already_running=0
for pid in $(pgrep Connection_Manager.sh);do
   if xargs -0 </proc/$pid/cmdline | grep -q ... ;then # match arguments here
       already_running=1
       break
   fi
done
if ! [ $already_running -eq 1 ];then
    # run Connection_Manager.sh here
fi
1

Why not simply actually use locking?

#!/bin/bash
if [[ -f /tmp/$0.lock ]]; then
    echo "$0 is locked."
    exit 1
else
    touch /tmp/$0.lock
    trap "rm -f /tmp/$0.lock" EXIT
fi
# The rest of the script
3
  • I thought of using lock but i want to do this without creating any temporary files. Already i am using some temp files for the script. Dec 25, 2013 at 6:51
  • It's insecure (anyone could run a process with a matching name), but you can avoid tempfiles with if pgrep $(basename $0) 2> /dev/null; then echo "Already running"; exit 1; fi
    – DopeGhoti
    Dec 25, 2013 at 7:25
  • 1
    Thanks for the answer, after trying different ways, i finally chose the locking mechanism. I am applying a lock when a script is executed with some arguments and have given the name of the lock file <arg1_arg2> which i am deleting at the end of the script. This way i am able to have multiple instances of the script running with different arguments than the one already running and block multiple instances of the script with the same arguments so that the script is not executed twice with the arguments already being used in running instace which was my actual requirement. Dec 28, 2013 at 12:46
1

I wrote a locking script that already handles this, including the security issues of tempfile ownership. Works even under busybox.

The current version available at http://dev.gentoo.org/~robbat2/scripts/pidlock

It does check arguments sanely using /proc/*/cmdline, and sanely handles stale lockfiles. It's used for a few hundred cronjobs scattered over *.gentoo.org.

Example usage showing it working:

$ ( /usr/local/bin/pidlock  sleep 5 & ) ; sleep 0.1 ; /usr/local/bin/pidlock   sleep 5
Error! 'pidlock-sleep' is running already!

(The sleep 0.1 is there to have the first one time to start.)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .