Команда 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

Ответы:


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 включительно .


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


На полусвязанном примечании: 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скрипт и не выполнили его из вашей среды.


4
$(exit 42)пытается выполнить вывод exit 42в виде простой команды, которая не имеет смысла (она также не будет работать с yash). (exit 42)(также запускается exitв подоболочке, но оставляет свои выходные данные в покое) более логичным и более переносимым (даже для csh или оболочки Bourne).
— Стефан Шазелас
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.