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

25

Existe um comando padrão do Unix 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 pode ser fork-execed e deixa 56 como o código de saída quando o processo sai. Os coins = exit e return de builtins são inadequados para o que estou procurando porque eles afetam a própria shell invocando saindo dele. <some cmd> deve ser algo que eu possa executar em contextos que não sejam de shell - por exemplo, invocando a partir de um script Python com subprocess .

Por exemplo, /usr/bin/false sempre sai imediatamente com o código de retorno 1, mas 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 padrão do Unix que possa fazer isso por mim.

    
por Chris 10.10.2016 / 04:51

5 respostas

37

  1. Uma função baseada em return funcionaria e evita a necessidade de abrir e fechar outro shell, (conforme Comentário de Tim Kennedy ):

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

    Saída:

    56
    
  2. usando exit em um subshell:

    (exit 56)
    

    Com shells diferentes de ksh93 , isso implica em bifurcar um processo extra, por isso é menos eficiente que o anterior.

  3. bash / zsh / ksh93 apenas truque:

    . <( echo return 56 )
    

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

  4. funções lambda de zsh :

    (){return 56}
    
por 10.10.2016 / 05:43
17

Não existe um comando UNIX padrão para apenas retornar um valor específico. O GNU Core Utilies fornece apenas true e false .

No entanto, você pode implementá-lo facilmente como ret :

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

Compilação:

cc ret.c -o ret

E corra:

./ret 56 ; echo $?

Impressões:

56

Se você precisa disso para trabalhar em qualquer lugar (onde o bash está disponível, isto é) 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 .

    
por 10.10.2016 / 13:32
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 interpretador de qualquer idioma que tenha a capacidade de sair com um status de saída arbitrário. sh é o mais óbvio:

sh -c 'exit 56'

Com a maioria das implementações sh , isso é limitado aos códigos de saída 0 a 255 ( sh aceitará valores maiores, mas poderá truncá-lo ou até mesmo enviar um sinal para o processo executando sh como com ksh93 para códigos 257 a 320).

Um código de saída pode ser qualquer valor inteiro ( int ), mas você precisa recuperá-lo com a interface waitid() para que o valor não seja truncado para 8 bits (no Linux, ainda truncado com waitid() bem embora). Portanto, é 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'

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

Com o NetBSD find , você pode fazer:

find / -exit 56

1 exit é o comando padrão para fazer isso, mas sendo um shell especial embutido , não há exigência de que haja também um comando com esse nome no sistema de arquivos, como para built-ins regulares, e a maioria dos sistemas não incluirá um

    
por 10.10.2016 / 14:02
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.c e gcc -o returncode returncode.c

    
por 10.10.2016 / 17:59
0

Eu não tinha certeza se o seu único problema com o comando exit foi sair do shell atual, mas se for o caso, 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 script .sh e executá-lo em seu ambiente.

    
por 10.10.2016 / 17:45