Команда 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
Це справді звучить як XYProblem : яка кінцева мета цього? Навіщо вам потрібна команда, яка повертає як код виходу номер, який ви їй даєте?
Олів'є Дулак

1
Ну, у вас є trueі falseвбудовані модулі , якщо вам потрібно повернути 0 або 1.
gardenhead

1
пов’язана: (не портативна) найменша програма для повернення фіксованого часу компіляції: muppetlabs.com/~breadbox/software/tiny/teensy.html
Флоріан Кастеллайн

Відповіді:


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 не працює.
Джошуа

@Joshua: можливо, це і є? але тоді ця афекта була успішною, і у вас є $? встановити 0 ...;)
Олів'є Дулак

@OlivierDulac: Це не так. Він випускає помилку розбору.
Джошуа

17

Не існує стандартної команди UNIX для повернення певного значення. Основні програми GNU надають 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 Дякую за те, що вказав на це. Як згадується в ОП, я якимось чином вважав GNU - навіть незважаючи на те, що в самому питанні зазначено "Unix".
tmh

14

Якщо вам потрібно, щоб стан виходу був встановлений виконаними командами. Там немає виділеної команди для цього 1 , але ви можете використовувати інтерпретатор будь-якої мови , який має можливість для виходу з довільним статусом виходу. shє найбільш очевидним:

sh -c 'exit 56'

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

Вихідним кодом може бути будь-яке значення integer ( int), але зауважте, що вам потрібно отримати його за допомогою waitid()інтерфейсу, щоб значення не було усічене до 8 біт (в Linux воно все ще обрізане waitid()). Отже, чому рідко (і не дуже гарно) використовувати вихідні коди вище 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 саме зараз, і це працює на мене.

Редагувати: Вибачте, я пропустив частину запуску її поза контекстом оболонки. У такому випадку THS не допоможе, не перетворивши його в .shсценарій і не виконавши це з вашого оточення.


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