Making zsh jobs -p behave as in bash

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP












1















Is there a way to make jobs -p in zsh behave as in bash, ie. give
only a number, such that one can do kill $(jobs -p)?










share|improve this question
























  • jobs -p gives pgids, not pids. If you want pids, look at the $jobstates special associative array.

    – Stéphane Chazelas
    Jan 8 at 23:28











  • @StéphaneChazelas, see edit.

    – Toothrot
    Jan 8 at 23:45















1















Is there a way to make jobs -p in zsh behave as in bash, ie. give
only a number, such that one can do kill $(jobs -p)?










share|improve this question
























  • jobs -p gives pgids, not pids. If you want pids, look at the $jobstates special associative array.

    – Stéphane Chazelas
    Jan 8 at 23:28











  • @StéphaneChazelas, see edit.

    – Toothrot
    Jan 8 at 23:45













1












1








1








Is there a way to make jobs -p in zsh behave as in bash, ie. give
only a number, such that one can do kill $(jobs -p)?










share|improve this question
















Is there a way to make jobs -p in zsh behave as in bash, ie. give
only a number, such that one can do kill $(jobs -p)?







zsh jobs






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 8 at 23:45







Toothrot

















asked Jan 8 at 23:12









ToothrotToothrot

828521




828521












  • jobs -p gives pgids, not pids. If you want pids, look at the $jobstates special associative array.

    – Stéphane Chazelas
    Jan 8 at 23:28











  • @StéphaneChazelas, see edit.

    – Toothrot
    Jan 8 at 23:45

















  • jobs -p gives pgids, not pids. If you want pids, look at the $jobstates special associative array.

    – Stéphane Chazelas
    Jan 8 at 23:28











  • @StéphaneChazelas, see edit.

    – Toothrot
    Jan 8 at 23:45
















jobs -p gives pgids, not pids. If you want pids, look at the $jobstates special associative array.

– Stéphane Chazelas
Jan 8 at 23:28





jobs -p gives pgids, not pids. If you want pids, look at the $jobstates special associative array.

– Stéphane Chazelas
Jan 8 at 23:28













@StéphaneChazelas, see edit.

– Toothrot
Jan 8 at 23:45





@StéphaneChazelas, see edit.

– Toothrot
Jan 8 at 23:45










1 Answer
1






active

oldest

votes


















3














jobs reports about jobs, which can have more than one process.



When interactive, jobs are places in process groups, so they can be suspended/resumed/interrupted as a whole.



jobs -p (in both zsh and bash) return the process group id of each job, not the process ids of all the processes in the job.



When the shell doesn't run interactively (where there's no job control), the shell reports the pid of the process that would have been the process group leader if there had been job control (which may not be the same as the one returned in $! by the way).



$ sleep 1 | sleep 20 &
[1] 29643 29644
$ jobs -p
[1] + 29643 done sleep 1 |
running sleep 20


zsh reports that for job 2 of pgid 29643, zsh started 2 processes, one of which is already done, the other still running.



If you want to get the pgids only like in bash, you can pipe that do:



awk '/^[/print $3'


If you want to get the pids in the job (only the ones started by the shell), you can look at the $jobstates special associative array:



$ typeset jobstates
jobstates=( 1 'running:+:29643=done:29644=running' )


To extract the pids of the processes still running in job 1:



$ echo $$(M)$(s/:/)jobstates[1]:#*=running%=*
29644


Now if you want to kill those jobs, you'd want to kill the process groups (in interactive shells), i.e. the whole jobs, not one process at random in the job.



You can kill the process group of id 29643 with kill -- -29643, kill 29643 would only kill the process of id 29643 (which is already dead in our example above).



Here, it would make more sense to pass job numbers instead of pid or pgid (which wouldn't work in non-interactive shells) to kill. That's what the job numbers are for:



kill %$(k)^jobstates


Unfortunately, I don't think bash has a reliable equivalent.



bash-4.4$ sleep $(: '
> [213] ...') 2134 &
[1] 29856
bash-4.4$ jobs
[1]+ Running sleep $(: '
[213] ...') 2134 &


It's difficult to extract the job numbers reliably from that. (I also find that even while kill %; do continue; done doesn't work because of what looks like some race condition bug).



Note that when not running interactively, there's no job control, so when you do kill %1 to kill the job number 1, that job doesn't have a process group. So as a poor man's approximation, the shell (both bash and zsh) will kill each process it knows about individually instead. In our example above, instead of:



kill(-29643, SIGTERM);


it will do:



kill(29643, SIGTERM);
kill(29644, SIGTERM);


It will not kill the other processes (if any) that those 2 processes have spawned themselves, though it's still better than killing only 29643 like in your kill $(jobs -p) approach.






share|improve this answer
























    Your Answer








    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "106"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f493350%2fmaking-zsh-jobs-p-behave-as-in-bash%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    3














    jobs reports about jobs, which can have more than one process.



    When interactive, jobs are places in process groups, so they can be suspended/resumed/interrupted as a whole.



    jobs -p (in both zsh and bash) return the process group id of each job, not the process ids of all the processes in the job.



    When the shell doesn't run interactively (where there's no job control), the shell reports the pid of the process that would have been the process group leader if there had been job control (which may not be the same as the one returned in $! by the way).



    $ sleep 1 | sleep 20 &
    [1] 29643 29644
    $ jobs -p
    [1] + 29643 done sleep 1 |
    running sleep 20


    zsh reports that for job 2 of pgid 29643, zsh started 2 processes, one of which is already done, the other still running.



    If you want to get the pgids only like in bash, you can pipe that do:



    awk '/^[/print $3'


    If you want to get the pids in the job (only the ones started by the shell), you can look at the $jobstates special associative array:



    $ typeset jobstates
    jobstates=( 1 'running:+:29643=done:29644=running' )


    To extract the pids of the processes still running in job 1:



    $ echo $$(M)$(s/:/)jobstates[1]:#*=running%=*
    29644


    Now if you want to kill those jobs, you'd want to kill the process groups (in interactive shells), i.e. the whole jobs, not one process at random in the job.



    You can kill the process group of id 29643 with kill -- -29643, kill 29643 would only kill the process of id 29643 (which is already dead in our example above).



    Here, it would make more sense to pass job numbers instead of pid or pgid (which wouldn't work in non-interactive shells) to kill. That's what the job numbers are for:



    kill %$(k)^jobstates


    Unfortunately, I don't think bash has a reliable equivalent.



    bash-4.4$ sleep $(: '
    > [213] ...') 2134 &
    [1] 29856
    bash-4.4$ jobs
    [1]+ Running sleep $(: '
    [213] ...') 2134 &


    It's difficult to extract the job numbers reliably from that. (I also find that even while kill %; do continue; done doesn't work because of what looks like some race condition bug).



    Note that when not running interactively, there's no job control, so when you do kill %1 to kill the job number 1, that job doesn't have a process group. So as a poor man's approximation, the shell (both bash and zsh) will kill each process it knows about individually instead. In our example above, instead of:



    kill(-29643, SIGTERM);


    it will do:



    kill(29643, SIGTERM);
    kill(29644, SIGTERM);


    It will not kill the other processes (if any) that those 2 processes have spawned themselves, though it's still better than killing only 29643 like in your kill $(jobs -p) approach.






    share|improve this answer





























      3














      jobs reports about jobs, which can have more than one process.



      When interactive, jobs are places in process groups, so they can be suspended/resumed/interrupted as a whole.



      jobs -p (in both zsh and bash) return the process group id of each job, not the process ids of all the processes in the job.



      When the shell doesn't run interactively (where there's no job control), the shell reports the pid of the process that would have been the process group leader if there had been job control (which may not be the same as the one returned in $! by the way).



      $ sleep 1 | sleep 20 &
      [1] 29643 29644
      $ jobs -p
      [1] + 29643 done sleep 1 |
      running sleep 20


      zsh reports that for job 2 of pgid 29643, zsh started 2 processes, one of which is already done, the other still running.



      If you want to get the pgids only like in bash, you can pipe that do:



      awk '/^[/print $3'


      If you want to get the pids in the job (only the ones started by the shell), you can look at the $jobstates special associative array:



      $ typeset jobstates
      jobstates=( 1 'running:+:29643=done:29644=running' )


      To extract the pids of the processes still running in job 1:



      $ echo $$(M)$(s/:/)jobstates[1]:#*=running%=*
      29644


      Now if you want to kill those jobs, you'd want to kill the process groups (in interactive shells), i.e. the whole jobs, not one process at random in the job.



      You can kill the process group of id 29643 with kill -- -29643, kill 29643 would only kill the process of id 29643 (which is already dead in our example above).



      Here, it would make more sense to pass job numbers instead of pid or pgid (which wouldn't work in non-interactive shells) to kill. That's what the job numbers are for:



      kill %$(k)^jobstates


      Unfortunately, I don't think bash has a reliable equivalent.



      bash-4.4$ sleep $(: '
      > [213] ...') 2134 &
      [1] 29856
      bash-4.4$ jobs
      [1]+ Running sleep $(: '
      [213] ...') 2134 &


      It's difficult to extract the job numbers reliably from that. (I also find that even while kill %; do continue; done doesn't work because of what looks like some race condition bug).



      Note that when not running interactively, there's no job control, so when you do kill %1 to kill the job number 1, that job doesn't have a process group. So as a poor man's approximation, the shell (both bash and zsh) will kill each process it knows about individually instead. In our example above, instead of:



      kill(-29643, SIGTERM);


      it will do:



      kill(29643, SIGTERM);
      kill(29644, SIGTERM);


      It will not kill the other processes (if any) that those 2 processes have spawned themselves, though it's still better than killing only 29643 like in your kill $(jobs -p) approach.






      share|improve this answer



























        3












        3








        3







        jobs reports about jobs, which can have more than one process.



        When interactive, jobs are places in process groups, so they can be suspended/resumed/interrupted as a whole.



        jobs -p (in both zsh and bash) return the process group id of each job, not the process ids of all the processes in the job.



        When the shell doesn't run interactively (where there's no job control), the shell reports the pid of the process that would have been the process group leader if there had been job control (which may not be the same as the one returned in $! by the way).



        $ sleep 1 | sleep 20 &
        [1] 29643 29644
        $ jobs -p
        [1] + 29643 done sleep 1 |
        running sleep 20


        zsh reports that for job 2 of pgid 29643, zsh started 2 processes, one of which is already done, the other still running.



        If you want to get the pgids only like in bash, you can pipe that do:



        awk '/^[/print $3'


        If you want to get the pids in the job (only the ones started by the shell), you can look at the $jobstates special associative array:



        $ typeset jobstates
        jobstates=( 1 'running:+:29643=done:29644=running' )


        To extract the pids of the processes still running in job 1:



        $ echo $$(M)$(s/:/)jobstates[1]:#*=running%=*
        29644


        Now if you want to kill those jobs, you'd want to kill the process groups (in interactive shells), i.e. the whole jobs, not one process at random in the job.



        You can kill the process group of id 29643 with kill -- -29643, kill 29643 would only kill the process of id 29643 (which is already dead in our example above).



        Here, it would make more sense to pass job numbers instead of pid or pgid (which wouldn't work in non-interactive shells) to kill. That's what the job numbers are for:



        kill %$(k)^jobstates


        Unfortunately, I don't think bash has a reliable equivalent.



        bash-4.4$ sleep $(: '
        > [213] ...') 2134 &
        [1] 29856
        bash-4.4$ jobs
        [1]+ Running sleep $(: '
        [213] ...') 2134 &


        It's difficult to extract the job numbers reliably from that. (I also find that even while kill %; do continue; done doesn't work because of what looks like some race condition bug).



        Note that when not running interactively, there's no job control, so when you do kill %1 to kill the job number 1, that job doesn't have a process group. So as a poor man's approximation, the shell (both bash and zsh) will kill each process it knows about individually instead. In our example above, instead of:



        kill(-29643, SIGTERM);


        it will do:



        kill(29643, SIGTERM);
        kill(29644, SIGTERM);


        It will not kill the other processes (if any) that those 2 processes have spawned themselves, though it's still better than killing only 29643 like in your kill $(jobs -p) approach.






        share|improve this answer















        jobs reports about jobs, which can have more than one process.



        When interactive, jobs are places in process groups, so they can be suspended/resumed/interrupted as a whole.



        jobs -p (in both zsh and bash) return the process group id of each job, not the process ids of all the processes in the job.



        When the shell doesn't run interactively (where there's no job control), the shell reports the pid of the process that would have been the process group leader if there had been job control (which may not be the same as the one returned in $! by the way).



        $ sleep 1 | sleep 20 &
        [1] 29643 29644
        $ jobs -p
        [1] + 29643 done sleep 1 |
        running sleep 20


        zsh reports that for job 2 of pgid 29643, zsh started 2 processes, one of which is already done, the other still running.



        If you want to get the pgids only like in bash, you can pipe that do:



        awk '/^[/print $3'


        If you want to get the pids in the job (only the ones started by the shell), you can look at the $jobstates special associative array:



        $ typeset jobstates
        jobstates=( 1 'running:+:29643=done:29644=running' )


        To extract the pids of the processes still running in job 1:



        $ echo $$(M)$(s/:/)jobstates[1]:#*=running%=*
        29644


        Now if you want to kill those jobs, you'd want to kill the process groups (in interactive shells), i.e. the whole jobs, not one process at random in the job.



        You can kill the process group of id 29643 with kill -- -29643, kill 29643 would only kill the process of id 29643 (which is already dead in our example above).



        Here, it would make more sense to pass job numbers instead of pid or pgid (which wouldn't work in non-interactive shells) to kill. That's what the job numbers are for:



        kill %$(k)^jobstates


        Unfortunately, I don't think bash has a reliable equivalent.



        bash-4.4$ sleep $(: '
        > [213] ...') 2134 &
        [1] 29856
        bash-4.4$ jobs
        [1]+ Running sleep $(: '
        [213] ...') 2134 &


        It's difficult to extract the job numbers reliably from that. (I also find that even while kill %; do continue; done doesn't work because of what looks like some race condition bug).



        Note that when not running interactively, there's no job control, so when you do kill %1 to kill the job number 1, that job doesn't have a process group. So as a poor man's approximation, the shell (both bash and zsh) will kill each process it knows about individually instead. In our example above, instead of:



        kill(-29643, SIGTERM);


        it will do:



        kill(29643, SIGTERM);
        kill(29644, SIGTERM);


        It will not kill the other processes (if any) that those 2 processes have spawned themselves, though it's still better than killing only 29643 like in your kill $(jobs -p) approach.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Jan 9 at 0:23

























        answered Jan 8 at 23:46









        Stéphane ChazelasStéphane Chazelas

        302k55566919




        302k55566919



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Unix & Linux Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f493350%2fmaking-zsh-jobs-p-behave-as-in-bash%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown






            Popular posts from this blog

            How to check contact read email or not when send email to Individual?

            Bahrain

            Postfix configuration issue with fips on centos 7; mailgun relay