Today I observed a strange behavior I am hoping I can get some direction on.
Here’s what I’m doing…
With at least one process already running in background, I interrupt (Ctrl + Z) the foreground process and then place it in the background with bg.
Here are the results in zsh:
$ some-long-running-command
^Z
zsh: suspended some-long-running-command
$ bg
[2] - continued some-long-running-command
$ jobs
[1] + running other-command-previously-run
[2] - running some-long-running-command
$
And here’s what it looks like in bash:
$ other-command-previously-run &
[1] 12345
$ some-long-running-command
^Z
[2]+ Stopped some-long-running-command
$ bg
[2]+ some-long-running-command &
$ jobs
[1]- Running other-command-previously-run &
[2]+ Running some-long-running-command &
$
So why does bash keep the process placed in background with bg as the “current” process (indicated by “+” which will be resumed if fg is run), while zsh sets the “other” process as current? I can’t find any documentation suggesting the behavior would be different… Interestingly if you do several fg + ^Z + bg in zsh, the “current” process selection will “flip flop”.
Has anyone else seen this?
I can reproduce this behaviour in
bashandzsh.My TL;DR answer: the behaviour you see in
bashis documented. The behaviour you see inzshis not (that I’ve found), and I have a theory, which might be wrong.Bash:
The Bash Manual, section 7, "Job Control Basics" describes the behaviour of the builtin
bg:Thus, from the point of view of
bash, the current job is the last job either stopped in foreground or started in the background. This explains the behaviour noticed in the question:ZSH:
I can’t explain this for
zsh. Theman zshmiscpage, under sectionJOBS, explains whatzshmeans by the+and-injobs:It does not, however, explain what effect
bg,fgand^Zhave on the processes in terms of relegating them topreviousorcurrent.My theory, which I’ve yet to verify by pestering the nice folks over in
irc.freenode.net#zsh, is thatzshuses a "current-process stack";bgpushes thecurrentprocess to the end of the queue. This can be seen when playing with three processes thus:As we can see here,
oneandtwoare pushed down on the theoretical stack.three, being executed last(?) is thecurrent process, denoted by the+from thejobsoutput.After
threeis suspended, it is still the current process, but afterbg, it is pushed to thepreviousprocess andtwo, being the "top" process in the "stack" becomes the newcurrentprocess.This, however, is conjecture; like I said, I haven’t got documented proof of this, and, honestly, the
man zsh*pages are slightly complicated; I may have missed something.