FAQ
I realize this is way off topic (probably should be titled "WOT:...") for Oracle but #1, I don't currently belong to any good linux/redhat forums and #2, the issue found was from an Oracle maint. script :-)
Anyway, I'm on a RHEL 4.6 server (2.6.9-67.0.22.ELlargesmp) and noticed a given DBA maint script wasn't running. It turns out that the only difference between when it last ran and now is someone changed the shell to be "bash" -> #!/bin/bash vs. #!/bin/ksh. The script has a little if-test to start with, used as a way to determine if a previous iteration of the job is still running:

if [ `ps -ef|grep -cw $0` -gt 3 ]; then
echo "$0 is already running"
exit 2
fi

The problem is that when this "ps ..." command stream is run within an if-test, it returns a value 1 higher than under "ksh". So when run out of cron it returns 4 under "bash" and 3 under "ksh". I added "set -x" right before this command and here are the results:

(under ksh)
+ grep -cw /home/test.sh
+ [ 3 -gt 3 ]

(under bash)
++ ps -ef
++ grep -cw /home/test.sh
+ '[' 4 -gt 3 ']'

This change only happens when running that command stream as part of an if-test. So "ps -ef|grep -cw $0" returns "3" but "if [ `ps -ef|grep -cw $0` -gt 3 ]" evaluates to "4". Am I interpreting this correctly in saying that bash forks another process when evaluating a command as part of an if-test while ksh does not? Is there a more general way of explaining this difference is shell processing?

DAVID HERRING
DBA
Acxiom Corporation
EML [email protected]
TEL 630.944.4762
MBL 630.430.5988
1501 Opus Pl, Downers Grove, IL 60515, USA
WWW.ACXIOM.COM<http://www.acxiom.com/>

The information contained in this communication is confidential, is intended only for the use of the recipient named above, and may be legally privileged. If the reader of this message is not the intended recipient, you are hereby notified that any dissemination, distribution or copying of this communication is strictly prohibited. If you have received this communication in error, please resend this communication to the sender and delete the original message or any copy of it from your computer system. Thank you.

Search Discussions

  • Guillermo Alan Bort at Apr 15, 2012 at 6:38 pm
    I would be interested in seeing the output of ps -ef |grep -w $0 as well to
    see what processes you see. Run it both with KSH and BASH and you may find
    the difference there.
    hth
    Alan.-
    (prevent overquoting)
  • Radoulov, Dimitre at Apr 15, 2012 at 6:56 pm

    On 15/04/2012 19:45, Herring Dave - dherri wrote:
    So "ps -ef|grep -cw $0" returns "3" but "if [ `ps -ef|grep -cw $0` -gt 3 ]" evaluates to "4". Am I interpreting this correctly in saying that bash forks another process when evaluating a command as part of an if-test while ksh does not? Is there a more general way of explaining this difference is shell processing?
    [...]
    I believe this is related to the fact that some shells (the KornShell
    and Z-Shell) thread the last command in a pipeline differently:


    [[email protected] t]$ bash -c '(ps -ef|grep -w $0)'
    drado 2560 2559 0 20:17 pts/0 00:00:00 -bash
    drado 3164 2560 2 20:42 pts/0 00:00:00 bash -c (ps -ef|grep -w $0)
    drado 3165 3164 1 20:42 pts/0 00:00:00 bash -c (ps -ef|grep -w $0)
    drado 3167 3165 3 20:42 pts/0 00:00:00 grep -w bash

    [[email protected] t]$ ksh -c '(ps -ef|grep -w $0)'
    drado 3168 2560 3 20:42 pts/0 00:00:00 ksh -c (ps -ef|grep -w $0)
    drado 3170 3168 1 20:42 pts/0 00:00:00 grep -w ksh


    From the man pages (KornShell 93 Manual Page -
    www2.research.att.com/sw/download/man/man1/ksh.html):

    A /pipeline / is a sequence of one or more /commands / separated by *|*.
    The standard output of each command but the last is connected by a

    /pipe/ <http://www2.research.att.com/sw/download/man/man2/pipe.html>(2)
    to the standard input of the next command. Each command, _except
    possibly the last_, is run as a separate process; the shell waits for
    the last command to terminate.


    P.S. I though that this difference was relative only to shell built in
    commands tough ...
  • Jared Still at Apr 20, 2012 at 5:10 pm

    On Sun, Apr 15, 2012 at 10:45 AM, Herring Dave - dherri wrote:
    I realize this is way off topic (probably should be titled "WOT:...") for
    Oracle but #1, I don't currently belong to any good linux/redhat forums and
    #2, the issue found was from an Oracle maint. script :-)
    WOT = Wide Open Throttle

    Sometimes applies to Oracle I guess.

    Anyway, I'm on a RHEL 4.6 server (2.6.9-67.0.22.ELlargesmp) and noticed a
    given DBA maint script wasn't running. It turns out that the only
    difference between when it last ran and now is someone changed the shell to
    be "bash" -> #!/bin/bash vs. #!/bin/ksh. The script has a little if-test
    to start with, used as a way to determine if a previous iteration of the
    job is still running:

    if [ `ps -ef|grep -cw $0` -gt 3 ]; then
    echo "$0 is already running"
    exit 2
    fi
    There are better methods for doing this.

    Following is a function that creates a PID file and uses it for locking.
    Stale locks are handled.

    a possible issues with this - not useful as is on cluster, as other
    nodes could run the script.

    Anyway, it may be of some use.

    Jared Still
    Certifiable Oracle DBA and Part Time Perl Evangelist
    Oracle Blog: http://jkstill.blogspot.com
    Home Page: http://jaredstill.com

    ==== script =====

    9:49-poirot:ts20:jkstill-22 > expand -t3 locktest.sh
    :

    LOCKFILE=/tmp/testlock.lock

    function script_lock {
    typeset MY_LOCKFILE
    MY_LOCKFILE=$1

    # remove stale lockfile
    [ -r "$MY_LOCKFILE" ] && {
    PID=$(cat $MY_LOCKFILE)
    ACTIVE=$(ps --no-headers -p $PID)
    if [ -z "$ACTIVE" ]; then
    rm -f $MY_LOCKFILE
    fi
    }

    # set lock

    if (set -o noclobber; echo "$$" > "$MY_LOCKFILE") 2> /dev/null; then
    trap 'rm -f "$MY_LOCKFILE"; exit $?' INT TERM EXIT
    return 0
    else
    echo "Failed to acquire $LOCKFILE. Held by $(cat $LOCKFILE)"
    exit 1
    fi
    }

    function script_unlock {
    rm -f "$LOCKFILE"
    trap - INT TERM EXIT
    }

    script_lock $LOCKFILE

    echo press '<ENTER>...'
    read dummy

    script_unlock
  • Herring Dave - dherri at Apr 24, 2012 at 2:03 pm
    Thx Jared - I appreciate the followup and sharing different methods!
    I meant to initially share that the original solution is flawed and my intent is not to look for better methods of doing this but more for understanding details about the differences in ksh and bash with this particular situation. As others have suggested, I removed the count ("-c") from the if-test just to see better what's going on.

    In bash the commands:

    set -x
    ps -ef|grep -w $0
    if [ "`ps -ef|grep -w $0`" > "3" ]; then
    exit 1
    fi

    ... display:

    + ps -ef
    + grep -w ./bash.sh
    oracle 24865 28645 0 09:33 pts/0 00:00:00 /bin/bash ./bash.sh
    oracle 24869 24865 0 09:33 pts/0 00:00:00 grep -w ./bash.sh
    ++ ps -ef
    ++ grep -w ./bash.sh
    + '[' 'oracle 24865 28645 0 09:33 pts/0 00:00:00 /bin/bash ./bash.sh
    oracle 24870 24865 0 09:33 pts/0 00:00:00 /bin/bash ./bash.sh
    oracle 24872 24870 0 09:33 pts/0 00:00:00 grep -w ./bash.sh' ']'
    + exit 1

    In ksh the same commands display:

    + ps -ef
    + grep -w ./ksh.sh
    oracle 24954 28645 0 09:33 pts/0 00:00:00 /bin/ksh ./ksh.sh
    oracle 24956 24954 0 09:33 pts/0 00:00:00 grep -w ./ksh.sh
    + ps -ef
    + grep -w ./ksh.sh
    + [ oracle 24954 28645 0 09:33 pts/0 00:00:00 /bin/ksh ./ksh.sh
    oracle 24958 24954 0 09:33 pts/0 00:00:00 grep -w ./ksh.sh ]
    + > 3
    + exit 1

    So it appears that bash forks an extra process for a command stream within an if-test while ksh doesn't. Replacing the command stream with a literal the 2 shells match up.

    DAVID HERRING
    DBA
    Acxiom Corporation
    EML [email protected]
    TEL 630.944.4762
    MBL 630.430.5988
    1501 Opus Pl, Downers Grove, IL 60515, USA
    WWW.ACXIOM.COM<http://www.acxiom.com/>


    [Friend Us on Facebook]<http://www.facebook.com/acxiomcorp> [Link Us on LinkedIn] <http://www.linkedin.com/groupRegistration?gid)01735> [Follow Us on Twitter] <http://twitter.com/acxiom>

    [cid:[email protected]]
    ________________________________
    The information contained in this communication is confidential, is intended only for the use of the recipient named above, and may be legally privileged. If the reader of this message is not the intended recipient, you are hereby notified that any dissemination, distribution or copying of this communication is strictly prohibited. If you have received this communication in error, please resend this communication to the sender and delete the original message or any copy of it from your computer system. Thank you.

    From: Jared Still
    Sent: Friday, April 20, 2012 11:55 AM
    To: Herring Dave - dherri
    Cc: [email protected]
    Subject: Re: OT: bash vs. ksh subprocess counts


    On Sun, Apr 15, 2012 at 10:45 AM, Herring Dave - dherri wrote:
    I realize this is way off topic (probably should be titled "WOT:...") for Oracle but #1, I don't currently belong to any good linux/redhat forums and #2, the issue found was from an Oracle maint. script :-)

    WOT = Wide Open Throttle

    Sometimes applies to Oracle I guess.

    Anyway, I'm on a RHEL 4.6 server (2.6.9-67.0.22.ELlargesmp) and noticed a given DBA maint script wasn't running. It turns out that the only difference between when it last ran and now is someone changed the shell to be "bash" -> #!/bin/bash vs. #!/bin/ksh. The script has a little if-test to start with, used as a way to determine if a previous iteration of the job is still running:

    if [ `ps -ef|grep -cw $0` -gt 3 ]; then
    echo "$0 is already running"
    exit 2
    fi

    There are better methods for doing this.

    Following is a function that creates a PID file and uses it for locking.
    Stale locks are handled.

    a possible issues with this - not useful as is on cluster, as other nodes could run the script.

    Anyway, it may be of some use.

    Jared Still
    Certifiable Oracle DBA and Part Time Perl Evangelist
    Oracle Blog: http://jkstill.blogspot.com
    Home Page: http://jaredstill.com
    ==== script =====

    9:49-poirot:ts20:jkstill-22 > expand -t3 locktest.sh
    :

    LOCKFILE=/tmp/testlock.lock

    function script_lock {
    typeset MY_LOCKFILE
    MY_LOCKFILE=$1

    # remove stale lockfile
    [ -r "$MY_LOCKFILE" ] && {
    PID=$(cat $MY_LOCKFILE)
    ACTIVE=$(ps --no-headers -p $PID)
    if [ -z "$ACTIVE" ]; then
    rm -f $MY_LOCKFILE
    fi
    }

    # set lock

    if (set -o noclobber; echo "$$" > "$MY_LOCKFILE") 2> /dev/null; then
    trap 'rm -f "$MY_LOCKFILE"; exit $?' INT TERM EXIT
    return 0
    else
    echo "Failed to acquire $LOCKFILE. Held by $(cat $LOCKFILE)"
    exit 1
    fi
    }

    function script_unlock {
    rm -f "$LOCKFILE"
    trap - INT TERM EXIT
    }

    script_lock $LOCKFILE

    echo press '<ENTER>...'
    read dummy

    script_unlock

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouporacle-l @
categoriesoracle
postedApr 15, '12 at 5:47p
activeApr 24, '12 at 2:03p
posts5
users4
websiteoracle.com

People

Translate

site design / logo © 2023 Grokbase