You are not logged in.

#1 2009-09-27 21:03:36

slightlystoopid
Member
Registered: 2009-09-10
Posts: 61

wc within a bash script (command substitution)

I want a script to check for running occurrences of itself in order to close superfluous instances, but I found it closing all instances. So I made a script to only check for instances of itself:

#!/bin/bash
#
# Word Count Test

echo `pidof -x scriptaurus`
echo `pidof -x scriptaurus | wc -w`
sleep 10000

Output:

[~]$ scriptaurus
13445
2

From another terminal:

[~]$ echo `pidof -x scriptaurus`
13445
[~]$ echo `pidof -x scriptaurus | wc -w`
1

Is there some basic technicality behind doing this I don't realize?

Last edited by slightlystoopid (2009-09-30 00:09:50)


One nation, under the corporatocracy, indivisible, with liberty for them.

Really, I can understand the Supreme Court's rulings. Afterall, corporations are people just like us, with love and feelings, hopes and dreams, and a limited lifespan to do it all in... oh wait, nevermind. I was thinking of same-sex marriage.

Offline

#2 2009-09-27 21:47:06

Garns
Member
Registered: 2008-05-28
Posts: 239

Re: wc within a bash script (command substitution)

Bash spawns a subshell to compute the result of a command substitution, I am not sure why this doesn't happen if there is only one command, possibly some kind of optimization.

You can see this if you  add ps inside the command substitution:

#!/bin/bash

echo `pidof -x scriptaurus`
printf  "`pidof -x scriptaurus | wc -w;ps`\n"

prints:

 ./scriptaurus 
17331
2
  PID TTY          TIME CMD
16296 pts/3    00:00:00 bash
17331 pts/3    00:00:00 scriptaurus
17333 pts/3    00:00:00 scriptaurus
17335 pts/3    00:00:00 ps

Not sure what you are trying to achieve so I can't provide a workaround.

Offline

#3 2009-09-27 22:51:40

tlvb
Member
From: Sweden
Registered: 2008-10-06
Posts: 297
Website

Re: wc within a bash script (command substitution)

It is possible that you are looking for the variable $$ which contains pid of the current shell [1]
If I understood you correctly you wanted that when the script started it would kill other already running scripts of the same kind (except itself)?

#!/bin/bash
otherpids=$(pidof -x thescript | sed "s/$$//") #remove the current pid from the list of pids you want to kill
echo This is $$
for i in $otherpids; do
    echo killing $i
    kill $i
done
sleep 10000

Not everything has to be done with sed though, heres another one.

#!/bin/bash
for i in $(pidof -x thescript); do
    if [[ $i == $$ ]]; then
        echo This is $i
    else
        echo killing $i
        kill $i
    fi
done
sleep 10000

[1] http://www.dartmouth.edu/~rc/classes/ks … rames.html see "10. Preset variables".

Last edited by tlvb (2009-09-27 23:24:55)


I need a sorted list of all random numbers, so that I can retrieve a suitable one later with a binary search instead of having to iterate through the generation process every time.

Offline

#4 2009-09-28 12:46:39

slightlystoopid
Member
Registered: 2009-09-10
Posts: 61

Re: wc within a bash script (command substitution)

@Garns
ahhh, that makes sense now.

@tlvb
thanks for the site, lot of reference there. and thanks for the suggestion, but actually, I'm trying to ensure only the first instance survives. lemme show you the complete script so you'll see why:

#!/bin/bash
#
# Ensure all necessary filesystems mounted before starting deluge
# And unmount on exit

fsdirs="large larger music"
cd

### Check filesystem existence and mount ###
for fs in $fsdirs
do
    if [ -d $fs ] && [ -O $fs ]
    then
        mount $fs 2> /dev/null
    else
        zenity --error --text="Mount point does not exist or insufficient permissions. Stopping."
        exit
    fi
done

### Check for passing torrents ###
if [ -n "$*" ]
then
    deluge "$*" 2> /dev/null
else
    deluge 2> /dev/null
fi

### Allow only one instance of deluge-runner ###
pids=`mktemp`
pidof -x deluge-runner > $pids
num=`cat $pids | wc -w`
if [ $num -gt 1 ]
then
    rm -f $pids
    exit
else
    rm -f $pids
fi

### Ensure daemon is dead ###
until [ -z `pidof -x deluged` ]
do
    sleep 5
done

### Unmount upon completion ###
for fs in $fsdirs
do
    umount $fs 2> /dev/null
done

exit

All is well, btw. Just forgot how command substitution worked, I guess.


One nation, under the corporatocracy, indivisible, with liberty for them.

Really, I can understand the Supreme Court's rulings. Afterall, corporations are people just like us, with love and feelings, hopes and dreams, and a limited lifespan to do it all in... oh wait, nevermind. I was thinking of same-sex marriage.

Offline

#5 2009-09-28 15:13:47

tlvb
Member
From: Sweden
Registered: 2008-10-06
Posts: 297
Website

Re: wc within a bash script (command substitution)

Ok, but in your script, why are you creating a temporary file to store the pids?
(In this code piece I assumed that is deluge-runner, otherwise -o $$ won't work

#!/bin/bash
if [[ -n $(pidof -xo $$ pidtest) ]]; then
    echo An instance of the program is already running
    exit 1
fi
# #... rest of code ...
# sleep 1000

Even if you want to split it up a bit for readability you could do something like $pids = $(pidof -xo $$ pidtest) and then if [[ -n $pids ]]; then ...
However during my testing, I notice that there are some differences between, say

# 1
echo $(pidof -x bash | wc -w)
# and
# 2
foo=$(pidof -x bash)
echo $(echo $foo | wc -w)

I think that there might have something to do with when subshells are run.

Last edited by tlvb (2009-09-28 15:19:31)


I need a sorted list of all random numbers, so that I can retrieve a suitable one later with a binary search instead of having to iterate through the generation process every time.

Offline

#6 2009-09-28 17:20:00

slightlystoopid
Member
Registered: 2009-09-10
Posts: 61

Re: wc within a bash script (command substitution)

tlvb wrote:
#!/bin/bash
if [[ -n $(pidof -xo $$ pidtest) ]]; then
    echo An instance of the program is already running
    exit 1
fi
# #... rest of code ...
# sleep 1000

Yes! I had to stare at it for a second before my noggin figgered what it was saying. Much better solution. Thank you.


One nation, under the corporatocracy, indivisible, with liberty for them.

Really, I can understand the Supreme Court's rulings. Afterall, corporations are people just like us, with love and feelings, hopes and dreams, and a limited lifespan to do it all in... oh wait, nevermind. I was thinking of same-sex marriage.

Offline

#7 2009-09-29 23:32:53

slightlystoopid
Member
Registered: 2009-09-10
Posts: 61

Re: wc within a bash script (command substitution)

I tried rewriting that code with backticks instead of $(), but it doesn't work, even though it appears to return an empty string either way. I've read that they're both "functionally equivalent". Here's what I've written:

#!/bin/bash
#
# Ensure all necessary filesystems mounted before starting deluge
# And unmount on exit

fsdirs="large larger music"
cd

### Check filesystem existence and mount ###
for fs in $fsdirs
do
    if [ -d $fs ] && [ -O $fs ]
    then
        mount $fs 2> /dev/null
    else
        zenity --error --text="Mount point does not exist or insufficient permissions. Stopping."
        exit
    fi
done
echo "A $(pidof -xo $$ deluge-runner)" >> $HOME/bin/delugelog
echo "A `pidof -xo $$ deluge-runner`" >> $HOME/bin/delugelog
### Check for passing torrents ###
if [ -n "$*" ]
then
    deluge "$*" 2> /dev/null
else
    deluge 2> /dev/null
fi

### Allow only one instance of deluge-runner ###
if [[ -n $(pidof -xo $$ deluge-runner) ]]
then
    echo "B $(pidof -xo $$ deluge-runner)" >> $HOME/bin/delugelog
    echo "B `pidof -xo $$ deluge-runner`" >> $HOME/bin/delugelog
    exit
fi
if [ -n `pidof -xo $$ deluge-runner` ]
then
    echo "C $(pidof -xo $$ deluge-runner)" >> $HOME/bin/delugelog
    echo "C `pidof -xo $$ deluge-runner`" >> $HOME/bin/delugelog
    exit
fi

### Ensure daemon is dead ###
until [ -z `pidof -x deluged` ]
do
    sleep 5
done

### Unmount upon completion ###
for fs in $fsdirs
do
    umount $fs 2> /dev/null
done

exit

I open two instances and delugelog looks like this:

A 
A 
A 4840
A 4840
B 4840
B 4840
C 
C

Apparently what I've read is invalid, and $() is the only proper way to do this, is that correct? in all scripts where I would use backticks, should $() be used instead?

Last edited by slightlystoopid (2009-09-29 23:39:24)


One nation, under the corporatocracy, indivisible, with liberty for them.

Really, I can understand the Supreme Court's rulings. Afterall, corporations are people just like us, with love and feelings, hopes and dreams, and a limited lifespan to do it all in... oh wait, nevermind. I was thinking of same-sex marriage.

Offline

#8 2009-09-30 00:34:44

slightlystoopid
Member
Registered: 2009-09-10
Posts: 61

Re: wc within a bash script (command substitution)

huh, this is turning into a triple post, my bad, but it didn't belong in an edit. it wasn't the backticks causing problems, it was [[ vs [, which still doesn't make sense in my noggin, since test supports -n. furthermore, I'm using single brackets in the until statement, which hasn't been a problem.


One nation, under the corporatocracy, indivisible, with liberty for them.

Really, I can understand the Supreme Court's rulings. Afterall, corporations are people just like us, with love and feelings, hopes and dreams, and a limited lifespan to do it all in... oh wait, nevermind. I was thinking of same-sex marriage.

Offline

#9 2009-09-30 14:11:10

Gen2ly
Member
From: Sevierville, TN
Registered: 2009-03-06
Posts: 1,529
Website

Re: wc within a bash script (command substitution)

Backticks and $(...) are the same thing.  $(...) is preferable for a couple reasons:

http://bash-hackers.org/wiki/doku.php/m … hfaq/082?s[]=backtick

As for single and double brackets, I can't tell you alot about them but I do know that double brackets perform additional tests.


Setting Up a Scripting Environment | Proud donor to wikipedia - link

Offline

Board footer

Powered by FluxBB