27

Is there a standard Unix command that does something similar to my example below

$ <cmd here> 56
$ echo Return code was $?
Return code was 56
$

<cmd here> should be something that can be fork-execed and leaves 56 as the exit code when the process exits. The exit and return shell builtins are unsuitable for what I'm looking for because they affect the invoking shell itself by exiting out of it. <some cmd> should be something that I can execute in non-shell contexts - e.g., invoking from a Python script with subprocess.

E.g., /usr/bin/false always exits immediately with return code 1, but I'd like to control exactly what that return code is. I could achieve the same results by writing my own wrapper script

$ cat my-wrapper-script.sh # i.e., <some cmd> = ./my-wrapper-script.sh
#!/usr/bin/bash
exit $1
$ ./my-wrapper-script.sh 56
$ echo $?
56

but I'm hoping there happens to exist a standard Unix command that can do this for me.

  • 10
    exit is the only one I can think of, but it tends to end your shell. bash -c 'exit 56' or bash -c "exit $1" might work for you. – Tim Kennedy Oct 10 '16 at 3:25
  • 12
    How about (exit 56)? – cuonglm Oct 10 '16 at 5:19
  • 6
    This really sounds like a XYProblem : what is the ultimate goal of this? Why do you need a command that returns as exit code the number you give it? – Olivier Dulac Oct 10 '16 at 10:21
  • 1
    Well, you have the true and false built-ins if you need to return 0 or 1. – gardenhead Oct 10 '16 at 16:19
  • 1
    related: (non portable) smallest program to return a compile-time fixed value: muppetlabs.com/~breadbox/software/tiny/teensy.html – Florian Castellane Oct 11 '16 at 12:45
39
  1. A return based function would work, and avoids the need to open and close another shell, (as per Tim Kennedy's comment):

    freturn() { return "$1" ; } 
    freturn 56 ; echo $?
    

    Output:

    56
    
  2. using exit in a subshell:

    (exit 56)
    

    With shells other than ksh93, that implies forking an extra process so is less efficient than the above.

  3. bash/zsh/ksh93 only trick:

    . <( echo return 56 )
    

    (that also implies an extra process (and IPC with a pipe)).

  4. zsh's lambda functions:

    (){return 56}
    
  • Good thought. Unfortunately, my original question was not defined well enough - needing to "open and close another shell" was almost a requirement of what I wanted to do. I edited my question to require that <some cmd> is an execve()-able thing. – Chris Oct 10 '16 at 5:06
  • 2
    @Chris: For any shell command you can make it execve()able by converting it to /bin/sh -c ...originalcommand... – psmears Oct 10 '16 at 10:02
  • 3
    I am mildly disappointed that ?=56 doesn't work. – Joshua Oct 10 '16 at 18:41
  • @Joshua: maybe it does? but then this affectation was successful, and you have $? set to 0 ... ;) – Olivier Dulac Oct 11 '16 at 10:35
  • @OlivierDulac: It doesn't. It spits out a parse error. – Joshua Oct 11 '16 at 15:11
17

There is no standard UNIX command for just returning a specific value. The GNU Core Utilies provide true and false only.

However, you can easily implement this yourself as ret:

#include <stdlib.h>
int main(int argc, char *argv[]) {
  return argc > 1 ? atoi(argv[1]) : 0;
}

Compile:

cc ret.c -o ret

And run:

./ret 56 ; echo $?

Prints:

56

If you need this to work everywhere (where bash is available, that is) without installing any extra tools, you probably need to resort to the following command as @TimKennedy suggested in comments:

bash -c 'exit 56'

Note that the valid range of return values is 0..255 inclusive.

  • 1
    true and false are in Unix (and even POSIX) as well, not only in GNU. – Stéphane Chazelas Oct 10 '16 at 16:52
  • @StéphaneChazelas Thanks for pointing that out. As the OP mentioned bash, I somehow assumed GNU -- even though the question itself states 'Unix'. – tmh Oct 10 '16 at 16:56
14

If you need the exit status to be set by an executed commands. There is no dedicated command for that1, but you can use the interpreter of any language that has the capability to exit with an arbitrary exit status. sh is the most obvious one:

sh -c 'exit 56'

With most sh implementations, that's limited to exit codes 0 to 255 (sh will accept greater values but may truncate it or even cause a signal to be sent to the process executing sh like with ksh93 for codes 257 to 320).

An exit code can be any integer (int) value but note that you need to retrieve it with the waitid() interface so the value is not truncated to 8 bits (on Linux, it's still truncated with waitid() as well though). Hence why it's rare (and not a good idea) to use exit codes above 255 (use 0-123 for normal operation).

Alternatively:

awk 'BEGIN{exit 56}'
perl -e 'exit 56'
python -c 'exit(56)'
expect -c 'exit 56'

(those don't truncate the exit code to 8 bits).

With NetBSD find, you can do:

find / -exit 56

1exit is the standard command to do that but being a shell special builtin, there's no requirement that there also be a command by that name in the file system like for regular built-ins, and most systems won't include one

3
/* Public domain, http://creativecommons.org/publicdomain/zero/1.0/ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char **argv) {
    if(!strcasecmp(argv[0],"true")) return 0;
    else if (!strcasecmp(argv[0],"false")) return 1;
    else if(argc<2) {fputs("One argument required\n",stderr);return 1;}
    else if(!strcasecmp(argv[argc-1],"true")) return 0;
    else if(!strcasecmp(argv[argc-1],"false")) return 1;
    else return atoi(argv[argc-1]);
}

Save this in a file named returncode.c and gcc -o returncode returncode.c

  • On a semi-related note: 1) applying the CC0 license without naming yourself as an affirmer is probably not a good idea, and you should do it like this, 2) programs this small are too trivial for your copyright to matter, so you might as well leave out the license. – Rhymoid Oct 10 '16 at 16:53
  • 2
    (1) I don’t understand why you’re using argv[argc-1] instead of argv[1], and why you’re not complaining if argc>2. (2) I’d be inclined to do the argv[1] test before the argv[0] test, allowing the user to say true 56 or false 56 instead of returncode 56. You don’t give a message if argv[0] is a word and argc>0 — that could be confusing. (3) I’m obsessed with user-friendliness, so I’d use strcasecmp instead of strcmp. (4) I tend to validate parameters, and not use the return value of atoi without verifying it. For a 2¢ program like this, I guess it doesn’t matter. – G-Man Oct 10 '16 at 21:41
  • @G-Man Neither true nor false processes any argument in Linux systems – ThePiercingPrince Oct 11 '16 at 7:16
  • OK, that’s correct — they don’t processes any argument, including argv[0]; the programs /bin/true and /bin/false are different executables, with hard-coded exit codes. You’ve written a program that can be installed as both true and false (linked), which is clever. But the question asks how to get a user-specified exit status. Your program answers that question, but only if it is installed under a different filename. As long as you’re looking at argv anyway, I believe that doing it the way I suggest would maintain the level of cleverness, by avoiding the need for a third link. – G-Man Oct 11 '16 at 21:18
0

I wasn't exactly sure if your only problem with the exit command was it exiting out of the current shell, but if so, a subshell might work.

username@host$ $(exit 42)
username@host$ echo $?
42

I tested this on Cygwin Bash just now and it works for me.

Edit: Sorry I missed the part of running it outside a shell context. In that case thsi wouldn't help without wrapping it within a .sh script and executing that from your environment.

  • 4
    $(exit 42) tries to execute the output of exit 42 as a simple command which makes little sense (it also wouldn't work with yash). (exit 42) (also run exit in a subshell, but leaves its output alone) would make more sense and would be more portable (even to csh or the Bourne shell). – Stéphane Chazelas Oct 10 '16 at 16:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.