Making zsh jobs -p behave as in bash












0














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
    2 hours ago










  • @StéphaneChazelas, see edit.
    – Toothrot
    2 hours ago
















0














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
    2 hours ago










  • @StéphaneChazelas, see edit.
    – Toothrot
    2 hours ago














0












0








0







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 2 hours ago







Toothrot

















asked 3 hours ago









ToothrotToothrot

821519




821519












  • jobs -p gives pgids, not pids. If you want pids, look at the $jobstates special associative array.
    – Stéphane Chazelas
    2 hours ago










  • @StéphaneChazelas, see edit.
    – Toothrot
    2 hours ago


















  • jobs -p gives pgids, not pids. If you want pids, look at the $jobstates special associative array.
    – Stéphane Chazelas
    2 hours ago










  • @StéphaneChazelas, see edit.
    – Toothrot
    2 hours ago
















jobs -p gives pgids, not pids. If you want pids, look at the $jobstates special associative array.
– Stéphane Chazelas
2 hours ago




jobs -p gives pgids, not pids. If you want pids, look at the $jobstates special associative array.
– Stéphane Chazelas
2 hours ago












@StéphaneChazelas, see edit.
– Toothrot
2 hours ago




@StéphaneChazelas, see edit.
– Toothrot
2 hours ago










1 Answer
1






active

oldest

votes


















2














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









    2














    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




























      2














      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


























        2












        2








        2






        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 1 hour ago

























        answered 2 hours ago









        Stéphane ChazelasStéphane Chazelas

        300k54564916




        300k54564916






























            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.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • 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

            Entries order in /etc/network/interfaces

            新発田市

            Grub takes very long (several minutes) to open Menu (in Multi-Boot-System)