[Klug-general] Checking For Duplicate Instance Of Script

David Halliday david.halliday at gmail.com
Wed Dec 21 14:38:54 UTC 2011


I now have the script behaving as it should, this is a slightly longer
function than I had hoped for but as long as it works and I can call it
with one line command then the length of the function isn't such an issue.

I will carry on testing it some more, any feedback/ideas from people here?

checkForDuplicateScript () {
  #Name a temp file for use in this script:
  TMPFILE="/tmp/tempfile-$$-$(date +%s).tmp"
  #Get the name of the script:
  SCRIPTNAME=$(basename $0)
  #Declare INSTANCECOUNT as integer:
  declare -i INSTANCECOUNT
  #List all running processes matching the script name to a file
  # Do not include the copy of grep which will contain the name
  ps aux | grep "$SCRIPTNAME" | grep -v "grep" > $TMPFILE
  #Get the number of lines in the TEMPFILE
  # - wc: count the number of lines in the file
  # - cut: Filter to only the first portion of the output, not file name
etc...
  # - sed: Remove any non numeric characters from output
  INSTANCECOUNT=$( wc -l $TMPFILE | cut -d" " -f1 | sed -e "s/[^0-9]//g" )

  if [ "$INSTANCECOUNT" -gt "1" ]
  then
    echo "Extra instance found of script: $SCRIPTNAME"
    echo "Count of instances: $INSTANCECOUNT"
    echo "Output from ps:"
    cat $TMPFILE
    exit 1
  fi
}


On 21 December 2011 13:56, David Halliday <david.halliday at gmail.com> wrote:

> *I have solved the strange increment problem!*
>
> To demonstrate the issue I created this test script:
> #!/bin/bash
> #declare an int
> declare -i INSTANCECOUNT
>
> echo "basename: $(basename $0)"
>
> echo "raw ps output command hard coded:"
> ps aux | grep test3 | grep -v "grep" | wc -l
>
> echo "raw ps output command basename:"
>
> ps aux | grep $(basename $0) | grep -v "grep" | wc -l
>
> echo "Command substitution test"
> echo $(ps aux | grep $(basename $0) | grep -v "grep" | wc -l)
>
> #assign & output 1:
> INSTANCECOUNT=$(ps aux | grep $(basename $0) | grep -v "grep" | wc -l)
> echo "Count 1: $INSTANCECOUNT"
>
> #assign & output 2:
> INSTANCECOUNT=$(ps aux | grep $(basename $0) | grep -v "grep" | wc -l
> 2>/dev/null)
> echo "Count 2: $INSTANCECOUNT"
>
> #assign & output 3:
> INSTANCECOUNT=$(ps aux | grep test3 | grep -v "grep" | wc -l)
> echo "Count 3: $INSTANCECOUNT"
>
> #assign & output 4:
> INSTANCECOUNT=$(ps aux | grep $(basename $0) | grep -v "grep" | wc -l |
> sed -e "s/[^0-9]//g")
> echo "Count 4: $INSTANCECOUNT"
>
> This produced the output:
> raw output command hardcoded:
> 1
> raw output command:
> 1
> Command substitution test
> 2
> Count 1: 2
> Count 2: 2
> Count 3: 2
> Count 4: 2
>
> When I used another process, say grep for sql rather than $(basename $0)
> the counts were as expected!
> Then I twigged, this was an issue of the ps command running using command
> substitution. In sohort by using command substitution "$()" a sub process
> was being created this was in turn creating an extra entry within ps which
> went as soon as the command substitution finished. Having done work with
> sub processes and simultanious processing under bash before I should have
> known. For those interested some links:
>
>    - Subshells (slightly different but same behaviour in ps
>    demonstrated): http://tldp.org/LDP/abs/html/subshells.html
>    - bash internal variables ($BASHPID and $$ useful for looking at
>    processes and sub processes by ID):
>    http://tldp.org/LDP/abs/html/internalvariables.html
>
> Note, $BASHPID is fairly new, only in bash v4 and up, to test:
>
> echo $BASH_VERSINFO[0]
> If you have over version 4 then you can test with this in a script:
> #!/bin/bash
> echo "Bash ID: $$ : $BASHPID : $BASH_SUBSHELL"
> echo $(echo "Bash ID: $$ : $BASHPID : $BASH_SUBSHELL")
>
> Interesting results, and worth thinking about if you are writing clever
> scripts!
>
> So, as a result I'm not 100% trusting of my script and now I understand a
> little more why!
> *
> So, it's still on with the script/library!*
> For the sake of sanity I have made the change to my test case.
>
> controlLib.sh
> =========
> checkForDuplicateScript () {
>
>   SCRIPTNAME=$(basename $0)
>   #declare INSTANCECOUNT as
> integer
>   declare -i INSTANCECOUNT
>   INSTANCECOUNT=$(ps aux | grep "$SCRIPTNAME" | grep -v "grep" | wc -l
> 2>/dev/null)
>   if [ "$INSTANCECOUNT" -gt "2" ]
>   then
>     echo "Extra instance found of script: $SCRIPTNAME : Full ps output: "
>     ps aux | grep "$SCRIPTNAME"
>     echo "Instance Count: $INSTANCECOUNT : $BASHPID : $SCRIPTNAME"
>     exit 1
>   fi
> }
>
> Still produces the same behaviour, so I will presume that bash kindly
> allows you to have overkill on function declaration (that's how I have been
> getting away with it all this time, but being lazy will prevent that from
> now on).
>
> So, the game is still on!
>
>
> On 21 December 2011 12:37, David Halliday <david.halliday at gmail.com>wrote:
>
>> I'll give that a try but since all my other functions have been working
>> as expected to date with that format I'll put it down as overkill.
>> Functions Doc: http://tldp.org/LDP/abs/html/functions.html
>>
>> I'll give that a try to see if it's what is causing the strange behaviour.
>>
>>
>> On 21 December 2011 12:27, Laurence Southon <laurence at southon.uk.net>wrote:
>>
>>> On 20/12/11 21:32, David Halliday wrote:
>>> > function checkForDuplicateScript(){
>>>
>>> I don't know if it's the reason but that function declaration should be
>>> either:
>>>
>>> function checkForDuplicateScript { ... }
>>>
>>> or
>>>
>>> checkForDuplicateScript () { ... }
>>>
>>> Not the keyword 'function' and '()' at the same time.
>>>
>>> LS
>>> --
>>> Laurence Southon
>>> Tiger Computing, Bexley
>>> www.tiger-computing.co.uk
>>>
>>> _______________________________________________
>>> Kent mailing list
>>> Kent at mailman.lug.org.uk
>>> https://mailman.lug.org.uk/mailman/listinfo/kent
>>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.lug.org.uk/pipermail/kent/attachments/20111221/b2b0b3d4/attachment.htm>


More information about the Kent mailing list