Команда Unix, которая немедленно возвращает определенный код возврата?

28

Есть ли стандартная команда Unix, которая делает что-то похожее на мой пример ниже

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

<cmd here>должно быть чем-то, что может быть обработано ветвлением и оставляет 56 в качестве кода выхода при выходе из процесса. В exitи returnоболочках встроенных функций непригодны для того, что я ищу , потому что они влияют на самом вызывающую оболочку при выходе из него. <some cmd>должно быть что-то, что я могу выполнить в контекстах без оболочки - например, вызов из скрипта Python с помощью subprocess.

Например, /usr/bin/falseвсегда завершается немедленно с кодом возврата 1, но я бы хотел точно определить, что это за код возврата. Я мог бы достичь тех же результатов, написав свой собственный скрипт-обертку

$ 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

но я надеюсь, что существует стандартная команда Unix, которая может сделать это для меня.

Крис
источник
10
exitэто единственный, о котором я могу думать, но это имеет тенденцию заканчивать вашу оболочку. bash -c 'exit 56'или bash -c "exit $1"может работать на вас.
Тим Кеннеди
12
Как насчет (exit 56)?
Cuonglm
6
Это действительно звучит как проблема XY : какова конечная цель этого? Зачем вам нужна команда, которая возвращает в качестве кода выхода номер, который вы ей дали?
Оливье Дюлак
1
Ну, у вас есть trueи falseвстроенные модули , если вам нужно возвратить 0 или 1.
gardenhead
1
связанные: ( непереносимая
Флориан Кастеллан

Ответы:

39
  1. returnФункция , основанная будет работать, и избавляет от необходимости открывать и закрывать другую оболочку, (согласно Тим Кеннеди комментарий «s ):

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

    Выход:

    56
  2. используя exitв подоболочке:

    (exit 56)

    Для оболочек, отличных от ksh93, это подразумевает разветвление дополнительного процесса, поэтому он менее эффективен, чем выше.

  3. bash/ zsh/ ksh93Трюк:

    . <( echo return 56 )

    (это также подразумевает дополнительный процесс (и IPC с каналом)).

  4. zshлямбда-функции:

    (){return 56}
АРУ
источник
Хорошая мысль. К сожалению, мой первоначальный вопрос не был определен достаточно хорошо - необходимость «открыть и закрыть другую оболочку» была почти требованием того, что я хотел сделать. Я отредактировал мой вопрос, требуя, чтобы <some cmd>это была execve () - способная вещь.
Крис
2
@Chris: для любой команды оболочки вы можете сделать ее execve () способной, преобразовав ее в/bin/sh -c ...originalcommand...
psmears
3
Я слегка разочарован тем, что? = 56 не работает.
Джошуа
@ Джошуа: может быть, это так? но тогда эта аффектация прошла успешно, а у вас есть $? установить 0 ...;)
Оливье Дюлак
@OlivierDulac: нет. Выдает ошибку разбора.
Джошуа
17

Не существует стандартной команды UNIX для простого возврата определенного значения. Утилиты GNU Core предоставляют trueи falseтолько.

Тем не менее, вы можете легко реализовать это самостоятельно как ret:

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

Обобщение:

cc ret.c -o ret

И запустить:

./ret 56 ; echo $?

Печать:

56

Если вам нужно, чтобы это работало везде (где есть bash, то есть без установки каких-либо дополнительных инструментов), вам, вероятно, нужно прибегнуть к следующей команде, как предложено в комментариях @TimKennedy:

bash -c 'exit 56'

Обратите внимание, что допустимый диапазон возвращаемых значений составляет 0..255 включительно .

TMH
источник
1
trueи falseв Unix (и даже POSIX), а не только в GNU.
Стефан Шазелас
@ StéphaneChazelas Спасибо за указание на это. Как ОП упоминал bash, я как-то предположил GNU - хотя сам вопрос гласит «Unix».
TMH
14

Если вам нужно, чтобы состояние выхода было установлено выполненными командами. Для этого 1 нет выделенной команды , но вы можете использовать переводчик любого языка, который имеет возможность выхода с произвольным статусом выхода. shявляется наиболее очевидным:

sh -c 'exit 56'

В большинстве shреализаций это ограничено кодами выхода от 0 до 255 ( shбудет принимать большие значения, но может усекать его или даже вызывать отправку сигнала процессу, выполняющемуся shподобно ksh93 для кодов с 257 по 320).

Код выхода может быть любым значением integer ( int), но имейте в виду, что вам нужно получить его с помощью waitid()интерфейса, чтобы значение не было усечено до 8 бит ( waitid()хотя в Linux оно все еще усекается ). Следовательно, почему редко (и не очень хорошая идея) использовать коды выхода выше 255 (используйте 0-123 для нормальной работы).

В качестве альтернативы:

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

(они не усекают код выхода до 8 бит).

С NetBSD find вы можете сделать:

find / -exit 56

1exit - это стандартная команда, которая делает это, но, будучи специальной встроенной оболочкой , не требуется, чтобы в файловой системе была команда с таким именем, как для обычных встроенных команд, и большинство систем не будет включать ее

Стефан Шазелас
источник
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]);
}

Сохраните это в файле с именем returncode.cиgcc -o returncode returncode.c

ThePiercingPrince
источник
На полусвязанном примечании: 1) применение лицензии CC0 без указания себя в качестве аффирмера, вероятно, не очень хорошая идея, и вы должны делать это следующим образом , 2) такие маленькие программы слишком тривиальны, чтобы ваше авторское право не имело значения, поэтому вы может также пропустить лицензию.
Рифмоид
2
(1) Я не понимаю, почему вы используете argv[argc-1]вместо argv[1], и почему вы не жалуетесь, если argc>2. (2) Я был бы склонен сделать argv[1]тест перед argv[0]тестом, позволяя пользователю сказать true 56или false 56вместо returncode 56. Вы не даете сообщение, если argv[0]это слово и argc>0- это может сбить с толку. (3) Я одержим удобством использования, поэтому я бы использовал strcasecmpвместо strcmp. (4) Я склонен проверять параметры, а не использовать возвращаемое значение atoiбез его проверки. Для 2-ой программы, как эта, я думаю, это не имеет значения.
G-Man говорит: «Восстанови Монику»
@ G-Man Ни один из них trueне falseобрабатывает аргументы в системах Linux
ThePiercingPrince
Хорошо, это правильно - они не обрабатывают никаких аргументов, в том числе argv[0]; программы /bin/trueи /bin/falseразные исполняемые файлы, с жестко закодированными кодами выхода. Вы написали программу , которая может быть установлена , как и true и false(связанную), который является умным. Но вопрос состоит в том, как получить указанный пользователем статус выхода. Ваша программа отвечает на этот вопрос, но только если она установлена ​​под другим именем файла. Пока вы смотрите в argvлюбом случае, я полагаю, что выполнение того, что я предлагаю, поддержало бы уровень хитрости, избегая необходимости в третьей ссылке.
G-Man говорит: «Восстановите Монику»
0

Я не был уверен, что ваша единственная проблема с exitкомандой - выход из текущей оболочки, но если это так, то подоболочка может работать.

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

Я только что проверил это на Cygwin Bash, и оно работает для меня.

Изменить: Извините, я пропустил часть запуска его вне контекста оболочки. В этом случае это не помогло бы, если бы вы не поместили его в .shскрипт и не выполнили его из вашей среды.

Mihir
источник
4
$(exit 42)пытается выполнить вывод exit 42в виде простой команды, которая не имеет смысла (она также не будет работать с yash). (exit 42)(также запускается exitв подоболочке, но оставляет свои выходные данные в покое) более логичным и более переносимым (даже для csh или оболочки Bourne).
Стефан Шазелас