0

proc1.sh

#!/bin/sh
touch /tmp/proc1.signature.mutex
#do something for long time
sleep 100 
rm -rf /tmp/proc1.signature.mutex

proc2.sh

#!/bin/sh
touch /tmp/proc2.signature.mutex
#do something for long time
sleep 100 
rm -rf /tmp/proc2.signature.mutex

proc3.sh

#!/bin/sh
touch /tmp/proc3.signature.mutex
#do something for long time
sleep 100 
rm -rf /tmp/proc3.signature.mutex

core.sh

Now is there a way to wait for deleting /tmp/proc[?][*].signature.mutex all such file using loop or something and then continue further execution

How to achieve objective of core.sh

3
  • You can use trap so that the file .mutex is deleted on exit i.e: trap 'rm -f /tmp/proc3.signature.mutex' EXIT. Commented Oct 30, 2017 at 15:04
  • 1
    Have core.sh start the other scripts as background jobs, then use wait to wait for them to finish. No need for lock files (these aren't mutexes). Commented Oct 30, 2017 at 15:46
  • Why not simply loop and check if proc file with index less than scripts current one exists in tmp directory ? Commented May 17, 2019 at 0:23

3 Answers 3

4

A mutex is a mutual exclusive lock. Your procN.sh scripts never test whether the mutex is held by another process before "locking".

If you let core.sh start the other scripts, it would be easy for it to wait for the completion of them:

#!/bin/sh

./proc1.sh &
./proc2.sh &
./proc3.sh &

wait

# other processing

This removes the need for the lock files altogether. If that's not possible, consider

#!/bin/sh

while [ -e "$HOME/locks/proc1.signature.mutex" ] ||
      [ -e "$HOME/locks/proc2.signature.mutex" ] ||
      [ -e "$HOME/locks/proc3.signature.mutex" ]
then
    echo 'waiting...'
    sleep 10
done

# other processing

To avoid leaving files behind by the procN.sh scripts if they die of unnatural causes, use a trap:

#!/bin/sh

lockfile="$HOME/locks/proc1.signature.mutex"

while [ -e "$lockfile" ]; do
    echo 'Can not get lock. Waiting...' >&2
    sleep 10
done
## alternatively:
# [ -e "$lockfile" ] && { echo 'something is wrong' >&2; exit 1; }

trap 'rm "$lockfile"; exit' EXIT INT TERM HUP
touch "$lockfile"

# etc.
# no need to rm the lock file at the end

Note that there is a space between the -e "$lockfile" test and the touch in which another process may lock the same file.

To avoid this, use a lock directory instead:

#!/bin/sh

lockdir="$HOME/locks/proc1.signature.mutex"

while ! mkdir "$lockdir"; do
    echo 'Can not get lock. Waiting...' >&2
    sleep 10
done

trap 'rmdir "$lockdir"; exit' EXIT INT TERM HUP

# etc.
# no need to rmdir the lock dir at the end

You may also use a symbolic link in a similar way.

Note that I've used a path under $HOME for the lock files/directories. If using /tmp, any user could potentially lock your script out of action by simply creating the correct file/directory.

4
  • There probably should be warnings about /tmp usage as a local attacker could denial of service the file version with a broken symlink (and the directory version might use a -d check...) Commented Oct 30, 2017 at 18:35
  • @thrig Good point. Commented Oct 30, 2017 at 18:45
  • @thrig -e works on both files and directories, but you need -h to test existence of a symlink (it doesn't matter if it's broken) Commented Oct 30, 2017 at 20:54
  • IMHO checking if file with index less that current one should be sufficient. No need for 3 OR checks. Or have a single file which has PID of currently running script aka lockfile. That would add extra code for trapping exit or sigint and cleaning the lockfile and that should be enough - knowing that a file is used bu something should be enough of a sign for any proc script to avoid proceeding Commented May 17, 2019 at 0:27
0

I wrote https://github.com/acbits/sema for this exact reason. I haven't been active on SE for a long time and just noticed this question. I have tested it only on Linux

2
  • 1
    Please explain how this is used. Commented May 16, 2019 at 18:09
  • @Scott My comment formatting didn't look good. Please look at answer below. Commented May 16, 2019 at 23:44
-1

Use https://github.com/acbits/sema to use semaphores in shell scripts.

 A.sh 
_____________________________________________
#!/bin/sh

echo A.sh started
sema -c S1
./B.sh &
echo A.sh more work
echo waiting for B.sh to finish
sema -w S1
echo B.sh finished execution
echo A.sh do more work
# cleanup semaphores
sema -d S1
_____________________________________________

B.sh
_____________________________________________
#!/bin/sh

echo Hello from B.sh
sleep 5
sema -r S1
echo Bye bye from B.sh
____________________________________________

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.