tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: shell jobs -p



    Date:        Thu, 13 Sep 2018 17:22:46 +0200
    From:        Edgar =?iso-8859-1?B?RnXf?= <ef%math.uni-bonn.de@localhost>
    Message-ID:  <20180913152246.GM5254%trav.math.uni-bonn.de@localhost>

  | > You're using an old version, not NetBSD current (or 8) right?
  | 6.1, mostly (for the ash part), yes.

The jobs command implementation was just screwy back then.

  | Surely you've digested what SUS says about this. I didn't try too hard, 
  | but I didn't grasp it. Could you explain what SUS allows?

I use the current version of the POSIX standard, but yes...

The standard says that when jobs is run (and "the termination status of a
job is reported, so not "jobs -p") the job should be cleaned up.   I believe
that's just dump, "wait" is the way for scripts to clean up dead jobs.   Part
of the issue is that the POSIX wait command is primitive, and almost useless,
so by having the jobs command act that  way they provide a simple method
to "make all the old stuff go away" easily.    It's just the wrong solution.

  | > The dash behaviour (clearing the jobs table in a subshell) is technically
  | > correct (but as you say, makes life difficult)
  | I'm not sure whether we are talking about the same thing.

We are.

  | What I mean is that if you have background jobs running, jobs -p will 
  | surely list them.

Yes.

  | However, if you want to use jobs -p output in a script,
  | the only way is to run it inside $(...).

No, that's just the easy way.   You can also do

	jobs -p >/tmp/whatever

and then use the content of the file $(cat /tmp/whatever) if that is
what you need.   Then the jobs command is run in the correct
environment.

  | That's a (potential) subshell environment,

Well, technically, it is always that - it is just that when it can be 
determined no mods will be made, it can sometimes be avoided.
POSIX goes to great lengths to explain how this is needed and
how it might be done for "trap" but mostly just ignored it for "jobs"
which has the same issue.

  | and in dash, the output of $(jobs -p) is always empty.

It is in the -current (and I suspect 8.0) NetBSD sh too.   But I will
fix that soon.

  | While I suppose the words of SUS allow that, SUS also gives $(jobs -p) 
  | as an example, which, in dash, could better be written "". This cannot 
  | be intended.

Not intended no, but it is technically correct - I suspect that the example
needs extra explanation or special case handling, like is done with trap.
I will file a bug report about it with the people who look after this stuff.

  | > the correct way to handle things like this is to not make a sub-shell 
  | > to run "simple" command substitutions which do not affect the current 
  | > shell environment.

  | I don't get that. Either we're talking past each other or I simply don't 
  | understand what you mean.

Here it could be either of those ... I was talking about how the shell
could be implemented so that the behaviour that you want occurs.
I suspect you're more concerned about what you can do with current
shells.   Those are indeed different things entirely.

  | Can you give a way where jobs -p and [insert your code here] echo "$j" 
  | give the same output in dash?

	jobs -p >/tmp/mybobs
	j=$(cat /tmp/myjobs)
	rm /tmp/myjobs
	echo "$j"

Of course, you'd normally use mktemp(1) rather than "/tmp/myjobs"

  | > jinx$ ./sh /tmp/parallel.jobs.sh 4 1 2 3 4 5 6 7 8 9
  | Yes, that's the intended way (which I guess is obvious from the source).

Not so obvious, but I got there eventually...

  | Would you say parallel.list.sh is portable?

Yes, looks to be.   Not that I have gone over every line of it with great care
(and using echo rather than printf can sometimes be non-portable, you'd
observe that if any of the args to jobs contained \ sequences, and you're
using an echo that interprets those things.)    I'd advise always using printf
even if you do it something like

	echo()
	{
		NL='\n'
		case "$1" in
		-n)	NL=; shift;;
		esac
		printf "%s${NL}" "$*"
	}

and then just keep writing "echo" ...  (nb: that \n is really the 2 chars \ 
and n, not a pseudonum for a literal newline char, though that would also 
work.)

kre



Home | Main Index | Thread Index | Old Index