Solved

Checking jobs in a shell script.

Posted on 1998-05-04
10
267 Views
Last Modified: 2013-12-26
I'm trying to use jobs builtin to see which of the jobs that my shellscript spawned have exited.  But it just doesn't seem to work.  For example, consider the following:

hjstein@blinky:~$ cat jobtest
#!/bin/bash

tail -f ~/.bashrc >/dev/null &
jobs
hjstein@blinky:~$ ./jobtest
hjstein@blinky:~$ ps -aux | grep tail
hjstein  21272  1.0  0.4   880   316  ?  S   13:12   0:00 tail -f /home/hjstein
hjstein  21274  0.0  0.5   972   344  ?  S   13:12   0:00 grep tail
hjstein@blinky:~$

The tail is running, but jobs doesn't report anything.  WHY!?!?!?!

Also, how do I get around it?

This is on linux with bash.  zsh behaves the same way.

0
Comment
Question by:hj2
10 Comments
 
LVL 3

Expert Comment

by:braveheart
Comment Utility
tail is running on your initialisation file which means that it will periodically display the output of that file. jobs is running in a different shell so tail will not display its output.
0
 

Author Comment

by:hj2
Comment Utility
jobs is run by the same shell which ran tail, as is evident by running the same 2 commands by hand:

   hjstein@blinky:~$ tail -f ~/.bashrc >/dev/null &
   [1] 433
   hjstein@blinky:~$ jobs
   [1]+  Running                 tail -f ~/.bashrc >/dev/null &
   hjstein@blinky:~$

This is also evident by sourcing jobtest instead of running it:

   hjstein@blinky:~$ . jobtest
   [1]+  Running                 tail -f ~/.bashrc >/dev/null &
   hjstein@blinky:~$ . jobtest
   [1]-  Running                 tail -f ~/.bashrc >/dev/null &
   [2]+  Running                 tail -f ~/.bashrc >/dev/null &
   hjstein@blinky:~$ . jobtest
   [1]   Running                 tail -f ~/.bashrc >/dev/null &
   [2]-  Running                 tail -f ~/.bashrc >/dev/null &
   [3]+  Running                 tail -f ~/.bashrc >/dev/null &
   hjstein@blinky:~$

The only difference btw ". jobtest" and "./jobtest" is that the former is run by the current shell, and the latter is run in a subshell.

0
 
LVL 51

Expert Comment

by:ahoffmann
Comment Utility
The reason is that in bash scripts background jobs are childs
of init (PID = 1), while in an interactive bash they are a child
of the bash itself. So the jobs command cannot find them because
they are in a different program group.
See man bash for a rough description about JOB CONTROL, for more
details I think you have to step deeper into the sources of bash.

Your script will work with csh (and probably with tcsh also).
0
 

Author Comment

by:hj2
Comment Utility
ahoffmann writes:

   The reason is that in bash scripts background jobs are childs
   of init (PID = 1), while in an interactive bash they are a
   child of the bash itself.

Why is this?  I didn't notice any mention of this in the man page.  Do you have any reference for this (other than the source code)?


0
 

Author Comment

by:hj2
Comment Utility
I confirmed your answer with ps -l, so I'm ready to give you (ahoffmann) an A rating, but I'd still like to know:

a) why processes spawned by noninteractive shells are children of init instead of being children of the shell that spawned them, and

b) Is there any way around this under bourne shells (bash, sh, ksh, ...)?

If you don't know, then just say so, and I'll close the question.
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
LVL 51

Accepted Solution

by:
ahoffmann earned 200 total points
Comment Utility
As I said, please refer to man bash for the "program group"
staff.
That there is a difference for script and interactive, I also
found by testing ;-) so that's the reason I said you must look
at the sources for the hard details.

Why it is different for bash and sh? I don't know. But bash and
sh behave the same (ksh probably too) 'cause sh is the ancestor
of all those shells, while csh was a complete new approach.
0
 

Author Comment

by:hj2
Comment Utility
Ok.  I'm satisifed.  I finally found "set -m" in the man page, which infers that job control is on by default for interactive shells and off otherwise.  The section on job control infers that subprocesses will be children of the current shell when job control is on and will be children of init when job control is off.

Thanks for your help.

0
 
LVL 2

Expert Comment

by:seedy
Comment Utility
ahoffmann,
I am just curious here.  But on my host, HPUX10.10, both ksh and sh do not behave that way.  The background jobs are not owned by init, they are owned by the shell.  Here is what I get:

/user3/seedy/tmp> echo $0
sh

/user3/seedy/tmp> cat ./jobtst
#/usr/bin/sh
tail -f ~/.kshrc >/dev/null &
ps -l -u seedy
jobs  -l

/user3/seedy/tmp> ./jobtst
  F S   UID   PID  PPID  C PRI NI     ADDR   SZ    WCHAN TTY       TIME COMD
  1 R  1026 15225 15072  0 178 20  18d1980  108        - ttyp4     0:00 sh
  1 R  1026 15227 15225  3 178 20  175ba80   23        - ttyp4     0:00 ps
  1 S  1026 15226 15225  2 168 20  203c480    8 7ffe6000 ttyp4     0:00 tail
  1 S  1026 15072 14999  0 158 20  17ad980  107   b687c0 ttyp4     0:00 sh
[1] + 15226      Running                 <job name not known>

As you can see tail's ppid is not 1.  Ksh also behaves this way.

hj2, if you do a ps -l outside the jobtst script, the tail will
be owned by pid 1 - this because the shell that was executing jobtst has terminated and hence the tail process is inherited by init.
0
 

Author Comment

by:hj2
Comment Utility
Good observation.  I don't understand this process group business enough to figure out what's going on...

0
 
LVL 51

Expert Comment

by:ahoffmann
Comment Utility
Seedy, you're right: processes spawned by a shell get PID 1 if
their parrent dies.

hj2,  set -m   explains the things about the process groups
So my answer was right half the way, thanks for the points anyway
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
repeatEnd java challenge 42 83
Folder Comparison 12 52
sum28 challenge 31 95
zeroMAx challenge 20 76
Introduction: Hints for the grid button.  Nested classes, templated collections.  Squash that darned bug! Continuing from the sixth article about sudoku.   Open the project in visual studio. First we will finish with the SUD_SETVALUE messa…
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now