Why do high exit codes on Linux shells (>= 256) not work as expected?

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











up vote
1
down vote

favorite












I discovered a strange behaviour (reproducible with zsh and bash on my system):



$ # here everything is still normal
$ bash -c 'exit 1';echo $?
1
$ bash -c 'exit 255';echo $?
255
$ zsh -c 'exit 255';echo $?
255
$ # now it get's crazy
$ bash -c 'exit 256';echo $?
0
$ zsh -c 'exit 256';echo $?
0
$ # (leaving away zsh for now, it is always reproducible with both)
$ bash -c 'exit 257';echo $?
1
$ bash -c 'exit 267';echo $?
11


So after 256 it begins to count from 1 again. But why?



The bash man page does not indicate that there is a maximum number:



 exit [n]
Cause the shell to exit with a status of n. If n is omitted,
the exit status is that of the last command executed. A trap on
EXIT is executed before the shell terminates.


And this is highly confusing behaviour. If programs depend on that, it could lead to big problems.



So why does this happen? And why is not it documented?



x64, Fedora 26










share|improve this question





















  • It is documented in the EXIT STATUS section: "Exit statuses fall between 0 and 255, though, as explained below, the shell may use values above 125 specially."
    – xhienne
    Sep 26 '17 at 23:47














up vote
1
down vote

favorite












I discovered a strange behaviour (reproducible with zsh and bash on my system):



$ # here everything is still normal
$ bash -c 'exit 1';echo $?
1
$ bash -c 'exit 255';echo $?
255
$ zsh -c 'exit 255';echo $?
255
$ # now it get's crazy
$ bash -c 'exit 256';echo $?
0
$ zsh -c 'exit 256';echo $?
0
$ # (leaving away zsh for now, it is always reproducible with both)
$ bash -c 'exit 257';echo $?
1
$ bash -c 'exit 267';echo $?
11


So after 256 it begins to count from 1 again. But why?



The bash man page does not indicate that there is a maximum number:



 exit [n]
Cause the shell to exit with a status of n. If n is omitted,
the exit status is that of the last command executed. A trap on
EXIT is executed before the shell terminates.


And this is highly confusing behaviour. If programs depend on that, it could lead to big problems.



So why does this happen? And why is not it documented?



x64, Fedora 26










share|improve this question





















  • It is documented in the EXIT STATUS section: "Exit statuses fall between 0 and 255, though, as explained below, the shell may use values above 125 specially."
    – xhienne
    Sep 26 '17 at 23:47












up vote
1
down vote

favorite









up vote
1
down vote

favorite











I discovered a strange behaviour (reproducible with zsh and bash on my system):



$ # here everything is still normal
$ bash -c 'exit 1';echo $?
1
$ bash -c 'exit 255';echo $?
255
$ zsh -c 'exit 255';echo $?
255
$ # now it get's crazy
$ bash -c 'exit 256';echo $?
0
$ zsh -c 'exit 256';echo $?
0
$ # (leaving away zsh for now, it is always reproducible with both)
$ bash -c 'exit 257';echo $?
1
$ bash -c 'exit 267';echo $?
11


So after 256 it begins to count from 1 again. But why?



The bash man page does not indicate that there is a maximum number:



 exit [n]
Cause the shell to exit with a status of n. If n is omitted,
the exit status is that of the last command executed. A trap on
EXIT is executed before the shell terminates.


And this is highly confusing behaviour. If programs depend on that, it could lead to big problems.



So why does this happen? And why is not it documented?



x64, Fedora 26










share|improve this question













I discovered a strange behaviour (reproducible with zsh and bash on my system):



$ # here everything is still normal
$ bash -c 'exit 1';echo $?
1
$ bash -c 'exit 255';echo $?
255
$ zsh -c 'exit 255';echo $?
255
$ # now it get's crazy
$ bash -c 'exit 256';echo $?
0
$ zsh -c 'exit 256';echo $?
0
$ # (leaving away zsh for now, it is always reproducible with both)
$ bash -c 'exit 257';echo $?
1
$ bash -c 'exit 267';echo $?
11


So after 256 it begins to count from 1 again. But why?



The bash man page does not indicate that there is a maximum number:



 exit [n]
Cause the shell to exit with a status of n. If n is omitted,
the exit status is that of the last command executed. A trap on
EXIT is executed before the shell terminates.


And this is highly confusing behaviour. If programs depend on that, it could lead to big problems.



So why does this happen? And why is not it documented?



x64, Fedora 26







bash shell zsh exit exit-code






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Sep 26 '17 at 21:44









rugk

271319




271319











  • It is documented in the EXIT STATUS section: "Exit statuses fall between 0 and 255, though, as explained below, the shell may use values above 125 specially."
    – xhienne
    Sep 26 '17 at 23:47
















  • It is documented in the EXIT STATUS section: "Exit statuses fall between 0 and 255, though, as explained below, the shell may use values above 125 specially."
    – xhienne
    Sep 26 '17 at 23:47















It is documented in the EXIT STATUS section: "Exit statuses fall between 0 and 255, though, as explained below, the shell may use values above 125 specially."
– xhienne
Sep 26 '17 at 23:47




It is documented in the EXIT STATUS section: "Exit statuses fall between 0 and 255, though, as explained below, the shell may use values above 125 specially."
– xhienne
Sep 26 '17 at 23:47










2 Answers
2






active

oldest

votes

















up vote
2
down vote













The POSIX manual page for the shell command exit(1p) states:




SYNOPSIS



exit [n]



DESCRIPTION



The exit utility shall cause the shell to exit with the exit status specified by the unsigned decimal integer n. If n is specified but its value is not between 0 and 255 inclusive, the exit status is undefined.




So for shells conforming to POSIX specifications, this behavior isn't undocumented, but it is also not necessarily portable.






share|improve this answer





























    up vote
    2
    down vote













    It is documented in the manual of the exit system function:




    The value of status may be 0, EXIT_SUCCESS, EXIT_FAILURE, [CX] [Option
    Start] or any other value, though only the least significant 8 bits
    (that is, status & 0377) shall be available to a waiting parent
    process. [Option End]




    Linux seems to stick to the standard very closely, and it doesn't let more than just the last 8 bits through.






    share|improve this answer


















    • 1




      Note that waitid() lets you access more than 8 bits of the return code on some systems, not Linux yet. It seems unlikely shells will start using that straight away. See austingroupbugs.net/view.php?id=594 austingroupbugs.net/view.php?id=947 austingroupbugs.net/view.php?id=597 austingroupbugs.net/view.php?id=1026 (the issue seems dear to @Schily, his shell already uses it and makes it available as $.sh.code
      – Stéphane Chazelas
      Sep 26 '17 at 22:07










    • Sorry $.sh.status, not $.sh.code (which is the si_code)
      – Stéphane Chazelas
      Sep 26 '17 at 22:23










    • @StéphaneChazelas Interesting, but I couldn't verify it on Linux. I tried int main() pid_t p; siginfo_t info; p = fork(); if(0==p) _exit(0xAABBCCDD); if(0>p)perror(0);exit(1); waitid(P_ALL,0,&info,WEXITED); printf("%Xn", info.si_code); printf("%Xn", info.si_status); and got 1 and DD which seems to indicate that indeed only the last 8 bits make it through.
      – PSkocik
      Sep 26 '17 at 22:26










    • Yes, like I said not on Linux yet. See Eric Blake commenting on whether the Kernel developers would agree to extend it in the first POSIX ticket I gave. You can test on FreeBSD or on SysV descendants like Solaris
      – Stéphane Chazelas
      Sep 26 '17 at 22:30











    • @StéphaneChazelas Sorry, I'm tired & I missed that part. It would sure be great if Linux let more of the exit bits though!
      – PSkocik
      Sep 26 '17 at 22:33










    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',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    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%2f394639%2fwhy-do-high-exit-codes-on-linux-shells-256-not-work-as-expected%23new-answer', 'question_page');

    );

    Post as a guest






























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    2
    down vote













    The POSIX manual page for the shell command exit(1p) states:




    SYNOPSIS



    exit [n]



    DESCRIPTION



    The exit utility shall cause the shell to exit with the exit status specified by the unsigned decimal integer n. If n is specified but its value is not between 0 and 255 inclusive, the exit status is undefined.




    So for shells conforming to POSIX specifications, this behavior isn't undocumented, but it is also not necessarily portable.






    share|improve this answer


























      up vote
      2
      down vote













      The POSIX manual page for the shell command exit(1p) states:




      SYNOPSIS



      exit [n]



      DESCRIPTION



      The exit utility shall cause the shell to exit with the exit status specified by the unsigned decimal integer n. If n is specified but its value is not between 0 and 255 inclusive, the exit status is undefined.




      So for shells conforming to POSIX specifications, this behavior isn't undocumented, but it is also not necessarily portable.






      share|improve this answer
























        up vote
        2
        down vote










        up vote
        2
        down vote









        The POSIX manual page for the shell command exit(1p) states:




        SYNOPSIS



        exit [n]



        DESCRIPTION



        The exit utility shall cause the shell to exit with the exit status specified by the unsigned decimal integer n. If n is specified but its value is not between 0 and 255 inclusive, the exit status is undefined.




        So for shells conforming to POSIX specifications, this behavior isn't undocumented, but it is also not necessarily portable.






        share|improve this answer














        The POSIX manual page for the shell command exit(1p) states:




        SYNOPSIS



        exit [n]



        DESCRIPTION



        The exit utility shall cause the shell to exit with the exit status specified by the unsigned decimal integer n. If n is specified but its value is not between 0 and 255 inclusive, the exit status is undefined.




        So for shells conforming to POSIX specifications, this behavior isn't undocumented, but it is also not necessarily portable.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Sep 26 '17 at 22:02









        Kusalananda

        106k14209327




        106k14209327










        answered Sep 26 '17 at 22:01









        Fox

        4,75111131




        4,75111131






















            up vote
            2
            down vote













            It is documented in the manual of the exit system function:




            The value of status may be 0, EXIT_SUCCESS, EXIT_FAILURE, [CX] [Option
            Start] or any other value, though only the least significant 8 bits
            (that is, status & 0377) shall be available to a waiting parent
            process. [Option End]




            Linux seems to stick to the standard very closely, and it doesn't let more than just the last 8 bits through.






            share|improve this answer


















            • 1




              Note that waitid() lets you access more than 8 bits of the return code on some systems, not Linux yet. It seems unlikely shells will start using that straight away. See austingroupbugs.net/view.php?id=594 austingroupbugs.net/view.php?id=947 austingroupbugs.net/view.php?id=597 austingroupbugs.net/view.php?id=1026 (the issue seems dear to @Schily, his shell already uses it and makes it available as $.sh.code
              – Stéphane Chazelas
              Sep 26 '17 at 22:07










            • Sorry $.sh.status, not $.sh.code (which is the si_code)
              – Stéphane Chazelas
              Sep 26 '17 at 22:23










            • @StéphaneChazelas Interesting, but I couldn't verify it on Linux. I tried int main() pid_t p; siginfo_t info; p = fork(); if(0==p) _exit(0xAABBCCDD); if(0>p)perror(0);exit(1); waitid(P_ALL,0,&info,WEXITED); printf("%Xn", info.si_code); printf("%Xn", info.si_status); and got 1 and DD which seems to indicate that indeed only the last 8 bits make it through.
              – PSkocik
              Sep 26 '17 at 22:26










            • Yes, like I said not on Linux yet. See Eric Blake commenting on whether the Kernel developers would agree to extend it in the first POSIX ticket I gave. You can test on FreeBSD or on SysV descendants like Solaris
              – Stéphane Chazelas
              Sep 26 '17 at 22:30











            • @StéphaneChazelas Sorry, I'm tired & I missed that part. It would sure be great if Linux let more of the exit bits though!
              – PSkocik
              Sep 26 '17 at 22:33














            up vote
            2
            down vote













            It is documented in the manual of the exit system function:




            The value of status may be 0, EXIT_SUCCESS, EXIT_FAILURE, [CX] [Option
            Start] or any other value, though only the least significant 8 bits
            (that is, status & 0377) shall be available to a waiting parent
            process. [Option End]




            Linux seems to stick to the standard very closely, and it doesn't let more than just the last 8 bits through.






            share|improve this answer


















            • 1




              Note that waitid() lets you access more than 8 bits of the return code on some systems, not Linux yet. It seems unlikely shells will start using that straight away. See austingroupbugs.net/view.php?id=594 austingroupbugs.net/view.php?id=947 austingroupbugs.net/view.php?id=597 austingroupbugs.net/view.php?id=1026 (the issue seems dear to @Schily, his shell already uses it and makes it available as $.sh.code
              – Stéphane Chazelas
              Sep 26 '17 at 22:07










            • Sorry $.sh.status, not $.sh.code (which is the si_code)
              – Stéphane Chazelas
              Sep 26 '17 at 22:23










            • @StéphaneChazelas Interesting, but I couldn't verify it on Linux. I tried int main() pid_t p; siginfo_t info; p = fork(); if(0==p) _exit(0xAABBCCDD); if(0>p)perror(0);exit(1); waitid(P_ALL,0,&info,WEXITED); printf("%Xn", info.si_code); printf("%Xn", info.si_status); and got 1 and DD which seems to indicate that indeed only the last 8 bits make it through.
              – PSkocik
              Sep 26 '17 at 22:26










            • Yes, like I said not on Linux yet. See Eric Blake commenting on whether the Kernel developers would agree to extend it in the first POSIX ticket I gave. You can test on FreeBSD or on SysV descendants like Solaris
              – Stéphane Chazelas
              Sep 26 '17 at 22:30











            • @StéphaneChazelas Sorry, I'm tired & I missed that part. It would sure be great if Linux let more of the exit bits though!
              – PSkocik
              Sep 26 '17 at 22:33












            up vote
            2
            down vote










            up vote
            2
            down vote









            It is documented in the manual of the exit system function:




            The value of status may be 0, EXIT_SUCCESS, EXIT_FAILURE, [CX] [Option
            Start] or any other value, though only the least significant 8 bits
            (that is, status & 0377) shall be available to a waiting parent
            process. [Option End]




            Linux seems to stick to the standard very closely, and it doesn't let more than just the last 8 bits through.






            share|improve this answer














            It is documented in the manual of the exit system function:




            The value of status may be 0, EXIT_SUCCESS, EXIT_FAILURE, [CX] [Option
            Start] or any other value, though only the least significant 8 bits
            (that is, status & 0377) shall be available to a waiting parent
            process. [Option End]




            Linux seems to stick to the standard very closely, and it doesn't let more than just the last 8 bits through.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Sep 26 '17 at 22:35

























            answered Sep 26 '17 at 21:54









            PSkocik

            17.2k24589




            17.2k24589







            • 1




              Note that waitid() lets you access more than 8 bits of the return code on some systems, not Linux yet. It seems unlikely shells will start using that straight away. See austingroupbugs.net/view.php?id=594 austingroupbugs.net/view.php?id=947 austingroupbugs.net/view.php?id=597 austingroupbugs.net/view.php?id=1026 (the issue seems dear to @Schily, his shell already uses it and makes it available as $.sh.code
              – Stéphane Chazelas
              Sep 26 '17 at 22:07










            • Sorry $.sh.status, not $.sh.code (which is the si_code)
              – Stéphane Chazelas
              Sep 26 '17 at 22:23










            • @StéphaneChazelas Interesting, but I couldn't verify it on Linux. I tried int main() pid_t p; siginfo_t info; p = fork(); if(0==p) _exit(0xAABBCCDD); if(0>p)perror(0);exit(1); waitid(P_ALL,0,&info,WEXITED); printf("%Xn", info.si_code); printf("%Xn", info.si_status); and got 1 and DD which seems to indicate that indeed only the last 8 bits make it through.
              – PSkocik
              Sep 26 '17 at 22:26










            • Yes, like I said not on Linux yet. See Eric Blake commenting on whether the Kernel developers would agree to extend it in the first POSIX ticket I gave. You can test on FreeBSD or on SysV descendants like Solaris
              – Stéphane Chazelas
              Sep 26 '17 at 22:30











            • @StéphaneChazelas Sorry, I'm tired & I missed that part. It would sure be great if Linux let more of the exit bits though!
              – PSkocik
              Sep 26 '17 at 22:33












            • 1




              Note that waitid() lets you access more than 8 bits of the return code on some systems, not Linux yet. It seems unlikely shells will start using that straight away. See austingroupbugs.net/view.php?id=594 austingroupbugs.net/view.php?id=947 austingroupbugs.net/view.php?id=597 austingroupbugs.net/view.php?id=1026 (the issue seems dear to @Schily, his shell already uses it and makes it available as $.sh.code
              – Stéphane Chazelas
              Sep 26 '17 at 22:07










            • Sorry $.sh.status, not $.sh.code (which is the si_code)
              – Stéphane Chazelas
              Sep 26 '17 at 22:23










            • @StéphaneChazelas Interesting, but I couldn't verify it on Linux. I tried int main() pid_t p; siginfo_t info; p = fork(); if(0==p) _exit(0xAABBCCDD); if(0>p)perror(0);exit(1); waitid(P_ALL,0,&info,WEXITED); printf("%Xn", info.si_code); printf("%Xn", info.si_status); and got 1 and DD which seems to indicate that indeed only the last 8 bits make it through.
              – PSkocik
              Sep 26 '17 at 22:26










            • Yes, like I said not on Linux yet. See Eric Blake commenting on whether the Kernel developers would agree to extend it in the first POSIX ticket I gave. You can test on FreeBSD or on SysV descendants like Solaris
              – Stéphane Chazelas
              Sep 26 '17 at 22:30











            • @StéphaneChazelas Sorry, I'm tired & I missed that part. It would sure be great if Linux let more of the exit bits though!
              – PSkocik
              Sep 26 '17 at 22:33







            1




            1




            Note that waitid() lets you access more than 8 bits of the return code on some systems, not Linux yet. It seems unlikely shells will start using that straight away. See austingroupbugs.net/view.php?id=594 austingroupbugs.net/view.php?id=947 austingroupbugs.net/view.php?id=597 austingroupbugs.net/view.php?id=1026 (the issue seems dear to @Schily, his shell already uses it and makes it available as $.sh.code
            – Stéphane Chazelas
            Sep 26 '17 at 22:07




            Note that waitid() lets you access more than 8 bits of the return code on some systems, not Linux yet. It seems unlikely shells will start using that straight away. See austingroupbugs.net/view.php?id=594 austingroupbugs.net/view.php?id=947 austingroupbugs.net/view.php?id=597 austingroupbugs.net/view.php?id=1026 (the issue seems dear to @Schily, his shell already uses it and makes it available as $.sh.code
            – Stéphane Chazelas
            Sep 26 '17 at 22:07












            Sorry $.sh.status, not $.sh.code (which is the si_code)
            – Stéphane Chazelas
            Sep 26 '17 at 22:23




            Sorry $.sh.status, not $.sh.code (which is the si_code)
            – Stéphane Chazelas
            Sep 26 '17 at 22:23












            @StéphaneChazelas Interesting, but I couldn't verify it on Linux. I tried int main() pid_t p; siginfo_t info; p = fork(); if(0==p) _exit(0xAABBCCDD); if(0>p)perror(0);exit(1); waitid(P_ALL,0,&info,WEXITED); printf("%Xn", info.si_code); printf("%Xn", info.si_status); and got 1 and DD which seems to indicate that indeed only the last 8 bits make it through.
            – PSkocik
            Sep 26 '17 at 22:26




            @StéphaneChazelas Interesting, but I couldn't verify it on Linux. I tried int main() pid_t p; siginfo_t info; p = fork(); if(0==p) _exit(0xAABBCCDD); if(0>p)perror(0);exit(1); waitid(P_ALL,0,&info,WEXITED); printf("%Xn", info.si_code); printf("%Xn", info.si_status); and got 1 and DD which seems to indicate that indeed only the last 8 bits make it through.
            – PSkocik
            Sep 26 '17 at 22:26












            Yes, like I said not on Linux yet. See Eric Blake commenting on whether the Kernel developers would agree to extend it in the first POSIX ticket I gave. You can test on FreeBSD or on SysV descendants like Solaris
            – Stéphane Chazelas
            Sep 26 '17 at 22:30





            Yes, like I said not on Linux yet. See Eric Blake commenting on whether the Kernel developers would agree to extend it in the first POSIX ticket I gave. You can test on FreeBSD or on SysV descendants like Solaris
            – Stéphane Chazelas
            Sep 26 '17 at 22:30













            @StéphaneChazelas Sorry, I'm tired & I missed that part. It would sure be great if Linux let more of the exit bits though!
            – PSkocik
            Sep 26 '17 at 22:33




            @StéphaneChazelas Sorry, I'm tired & I missed that part. It would sure be great if Linux let more of the exit bits though!
            – PSkocik
            Sep 26 '17 at 22:33

















             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f394639%2fwhy-do-high-exit-codes-on-linux-shells-256-not-work-as-expected%23new-answer', 'question_page');

            );

            Post as a guest













































































            Popular posts from this blog

            Peggy Mitchell

            Palaiologos

            The Forum (Inglewood, California)