I have a script

$ cat my.sh 
#! /bin/bash -
dirs -l > /tmp/test/dirs_record
jobs > /tmp/test/jobs_record

So when I source ./my.sh, it will output the dir stack and jobs in the invoking shell.

I have another script schedule.sh

#! /bin/bash -
while : ; do eval "${@}" ; sleep 10 ; done

Running source schedule.sh source ./my.sh in a bash shell can periodically record the dir stack and jobs in the invoking bash shell.

But I want to run other commands in the same shell, and want source schedule.sh source ./my.sh to record the up-to-date dir stack and jobs periodically, so I put it in background source schedule.sh source ./my.sh &, and then since jobs and dirs are running in a subshell instead of the invoking shell, any change to the jobs or dir stack to the invoking shell will not be recorded. See Why do `jobs` and `dirs` run in command subsitution, process substitution, pipeline, and background jobs output the same as in original shell?

How can I periodically record the dir stack and jobs of a shell without occupying the shell? For example, can I run a background job directly in the invoking shell?



You can do this with a signal trap, and running sleep && kill in the background:

$ cat monitor.sh
# monitor stuff in the background

# ensure this file is sourced, not executed: http://mywiki.wooledge.org/BashFAQ/109 
sourced() { [[ ${FUNCNAME[1]} == "source" ]]; }
sourced || { echo "source me"; exit 1; }
unset -f sourced


trap __usr1_trap USR1

__usr1_trap() {
    dirs -l >| /tmp/test/dirs_record
    jobs    >| /tmp/test/jobs_record
    __schedule_trap &

__schedule_trap() {
    sleep 60
    kill -USR1 $__MY_PID

# trigger the signal handler, which will reschedule itself
kill -USR1 $__MY_PID

Launch it with . /path/to/monitor.sh

Note that I use >| as the redirection operator in the signal handler because I run with set -o noclobber to avoid accidentally overwriting files: here we want to overwrite the files on purpose.

| improve this answer | |
  • Thanks. Is prefix __ naming convention to distinguish names created by you from those implicitly by the shell? – Tim Aug 2 '18 at 22:56
  • Yeah. I picked it up from some coding convention that "private methods" start with an underscore. I'd be unlikely to type it by accident. – glenn jackman Aug 2 '18 at 23:11
  • How would you stop it from running? trap "" USR1? – Tim Aug 2 '18 at 23:24
  • One strange problem when I run your script is that the signal stops being sent and trapped whenever the shell is idle i.e. without my running any command, Is it because __schedule_trap & need me to type RETURN key to finish sending the signal? – Tim Aug 2 '18 at 23:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.