Search code examples
linuxcsh

Csh script wait for multiple pid


Does the wait command work in a csh script to wait for more than 1 PID to finish?

Where the wait command waits for all the PID listed to complete before moving on to the next line

e.g.

wait $job1_pid $job2_pid $job3_pid
nextline

as the documentation online that I usually see only shows the wait command with only 1 PID, although I have read of using wait for multiple PID, like here : http://www2.phys.canterbury.ac.nz/dept/docs/manuals/unix/DEC_4.0e_Docs/HTML/MAN/MAN1/0522____.HTM

which says quote "If one or more pid operands are specified that represent known process IDs,the wait utility waits until all of them have terminated"


Solution

  • No, the builtin wait command in csh can only wait for all jobs to finish. The command in the documentation that you're referencing is a separate executable that is probably located at /usr/bin/wait or similar. This executable cannot be used for what you want to use it for.

    I recommend using bash and its more powerful wait builtin, which does allow you to wait for specific jobs or process ids.


    From the tcsh man page, wait waits for all background jobs. tcsh is compatible with csh, which is what the university's documentation you linked is referring to.

    wait The shell waits for all background jobs. If the shell is interactive, an interrupt will disrupt the wait and cause the shell to print the names and job numbers of all outstanding jobs.

    You can find this exact text on the csh documentation here.

    The wait executable described in the documentation is actually a separate command that waits for a list of process ids.

    However, the wait executable is not actually capable of waiting for the child processes of the running shell script and has no chance of doing the right thing in a shell script.

    For instance, on OS X, /usr/bin/wait is this shell script.

    #!/bin/sh
    # $FreeBSD: src/usr.bin/alias/generic.sh,v 1.2 2005/10/24 22:32:19 cperciva Exp $
    # This file is in the public domain.
    builtin `echo ${0##*/} | tr \[:upper:] \[:lower:]` ${1+"$@"}
    

    Anyway, I can't get the /usr/bin/wait executable to work reliably in a Csh script ... because the the background jobs are not child processes of the /usr/bin/wait process itself.

    #!/bin/csh -f
    
    setenv PIDDIR "`mktemp -d`"
    
    sleep 4 &
    
    ps ax | grep 'slee[p]' | awk '{ print $1 }' > $PIDDIR/job
    
    /usr/bin/wait `cat $PIDDIR/job`
    

    I would highly recommend writing this script in bash or similar where the builtin wait does allow you to wait for pids and capturing pids from background jobs is easier.

    #!/bin/bash
    
    sleep 4 &
    pid_sleep_4="$!"
    
    sleep 7 &
    pid_sleep_7="$!"
    
    wait "$pid_sleep_4"
    echo "waited for sleep 4"
    
    wait "$pid_sleep_7"
    echo "waited for sleep 7"
    

    If you don't want to rewrite the entire csh script you're working on, you can call out to bash from inside a csh script like so.

    #!/bin/csh -f
    
    bash <<'EOF'
    
    sleep 4 &
    pid_sleep_4="$!"
    
    sleep 7 &
    pid_sleep_7="$!"
    
    wait "$pid_sleep_4"
    echo "waited for sleep 4"
    
    wait "$pid_sleep_7"
    echo "waited for sleep 7"
    
    'EOF'
    

    Note that you must end that heredoc with 'EOF' including the single quotes.