Comando Unix que retorna imediatamente um código de retorno específico?


28

Existe um comando Unix padrão que faz algo semelhante ao meu exemplo abaixo

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

<cmd here>deve ser algo que possa ser executado em fork e deixa 56 como o código de saída quando o processo é encerrado. Os componentes internos exite returnshell não são adequados para o que estou procurando, pois afetam o próprio invocador ao sair dele. <some cmd>deve ser algo que eu possa executar em contextos não shell - por exemplo, invocar a partir de um script Python com subprocess.

Por exemplo, /usr/bin/falsesempre sai imediatamente com o código de retorno 1, mas eu gostaria de controlar exatamente o que é esse código de retorno. Eu poderia alcançar os mesmos resultados escrevendo meu próprio script de wrapper

$ 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

mas espero que exista um comando Unix padrão que possa fazer isso por mim.


10
exité o único que consigo pensar, mas tende a acabar com o seu shell. bash -c 'exit 56'ou bash -c "exit $1"pode funcionar para você.
— Tim Kennedy

12
Que tal (exit 56)?
— cuonglm

6
Isso realmente soa como um problema XY : qual é o objetivo final disso? Por que você precisa de um comando que retorne como código de saída o número fornecido?
— quer

1
Bem, você tem os truee falsebuilt-ins, se você precisa de retornar 0 ou 1.
— gardenhead

1
Relacionados: (não portátil) menor programa para retornar um valor de compilação em tempo fixo: muppetlabs.com/~breadbox/software/tiny/teensy.html
— Florian Castellane

Respostas:


39
  1. A returnfunção de base iria funcionar, e evita a necessidade de abrir e fechar outro shell, (como por Tim Kennedy comentário 's ):

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

    Saída:

    56
  2. usando exitem um subshell:

    (exit 56)

    Com cascas que não sejam ksh93, isso implica bifurcar um processo extra, portanto, é menos eficiente do que o descrito acima.

  3. bash/ zsh/ ksh93único truque:

    . <( echo return 56 )

    (isso também implica um processo extra (e IPC com um pipe)).

  4. zshFunções lambda de:

    (){return 56}

Bom pensamento. Infelizmente, minha pergunta original não foi bem definida - a necessidade de "abrir e fechar outro shell" era quase um requisito do que eu queria fazer. Eu editei minha pergunta para exigir que isso <some cmd>seja uma coisa executável ().
— 10286 Chris

2
@ Chris: Para qualquer comando da shell que pode torná-lo execve () poder, convertendo-a/bin/sh -c ...originalcommand...
— psmears

3
Estou levemente decepcionado que? = 56 não funcione.
— Joshua

@ Josué: talvez faz? mas essa afetação foi bem-sucedida e você tem $? definido como 0 ...;)
— Olivier Dulac 11/10

@OlivierDulac: Não. Ele cospe um erro de análise.
— Joshua

17

Não há comando UNIX padrão apenas para retornar um valor específico. Os utilitários principais do GNU fornecem truee falsesomente.

No entanto, você pode facilmente implementar isso como ret:

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

Compilar:

cc ret.c -o ret

E corra:

./ret 56 ; echo $?

Impressões:

56

Se você precisar que isso funcione em qualquer lugar (onde o bash está disponível, ou seja) sem instalar nenhuma ferramenta extra, você provavelmente precisará recorrer ao seguinte comando, como @TimKennedy sugerido nos comentários:

bash -c 'exit 56'

Observe que o intervalo válido de valores de retorno é 0..255 inclusive .


1
truee falseestão no Unix (e até no POSIX) também, não apenas no GNU.
— Stéphane Chazelas 10/10

@ StéphaneChazelas Obrigado por apontar isso. Como o OP mencionou o bash, de alguma forma assumi o GNU - embora a própria pergunta afirme 'Unix'.
— TMH

14

Se você precisar que o status de saída seja definido por um comando executado. Não existe um comando dedicado para esse 1 , mas você pode usar o intérprete de qualquer idioma que possua a capacidade de sair com um status de saída arbitrário. shé o mais óbvio:

sh -c 'exit 56'

Na maioria das shimplementações, isso é limitado aos códigos de saída de 0 a 255 ( shaceitará valores maiores, mas poderá truncá-lo ou até causar um sinal para o processo ser executado shcomo ksh93 nos códigos de 257 a 320).

Um código de saída pode ser qualquer intvalor inteiro ( ), mas observe que você precisa recuperá-lo com a waitid()interface para que o valor não seja truncado para 8 bits (no Linux, ele ainda é truncado waitid()também). Por isso, é raro (e não é uma boa ideia) usar códigos de saída acima de 255 (use 0-123 para operação normal).

Alternativamente:

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

(aqueles não truncam o código de saída para 8 bits).

Com o NetBSD find, você pode:

find / -exit 56

1exit é o comando padrão para fazer isso, mas, sendo um embutido especial do shell , não é necessário que também exista um comando com esse nome no sistema de arquivos, como para embutidos regulares, e a maioria dos sistemas não inclui um


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]);
}

Salve isso em um arquivo chamado returncode.cegcc -o returncode returncode.c


Em uma nota semi-relacionada: 1) aplicar a licença CC0 sem se nomear um afirmador provavelmente não é uma boa idéia, e você deve fazer assim , 2) programas pequenos assim são triviais demais para que seus direitos autorais sejam importantes; pode deixar de fora a licença.
— Rhymoid

2
(1) Eu não entendo por que você está usando argv[argc-1], em vez de argv[1], e por que você não está reclamando se argc>2. (2) Eu estaria inclinado a fazer o argv[1]teste antes do argv[0]teste, permitindo que o usuário dissesse true 56ou false 56não returncode 56. Você não dá uma mensagem se argv[0]for uma palavra e argc>0- isso pode ser confuso. (3) Eu sou obcecado pela facilidade de uso, então eu usaria em strcasecmpvez de strcmp. (4) Eu costumo validar parâmetros e não usar o valor de retorno atoisem verificar. Para um programa 2 ¢ como esse, acho que não importa.
— G-Man Diz 'Reinstate Monica'

@ G-Man Nem truenem falseprocessa qualquer argumento em sistemas Linux
— ThePiercingPrince

OK, está correto - eles não processam nenhum argumento, inclusive argv[0]; os programas /bin/truee /bin/falsesão executáveis ​​diferentes, com códigos de saída codificados. Você escreveu um programa que pode ser instalado como ambos true e false(ligada), que é inteligente. Mas a pergunta pergunta como obter um status de saída especificado pelo usuário. Seu programa responde a essa pergunta, mas somente se ele estiver instalado com um nome de arquivo diferente. Enquanto você estiver olhando de argvqualquer maneira, acredito que fazer da maneira que sugiro manteria o nível de inteligência, evitando a necessidade de um terceiro link.
— G-Man diz que 'Reinstate Monica'

0

Eu não tinha exatamente certeza se o seu único problema com o exitcomando era sair do shell atual, mas se sim, um subshell pode funcionar.

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

Eu testei isso no Cygwin Bash agora e funciona para mim.

Edit: Desculpe, eu perdi a parte de executá-lo fora de um contexto de shell. Nesse caso, isso não ajudaria sem envolvê-lo em um .shscript e executá-lo em seu ambiente.


4
$(exit 42)tenta executar a saída exit 42como um comando simples que faz pouco sentido (também não funcionaria yash). (exit 42)(também é executado exitem um subshell, mas deixa sua saída em branco) faria mais sentido e seria mais portátil (mesmo para o csh ou o shell Bourne).
— Stéphane Chazelas 10/10
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.