Неявный возврат в функциях bash?

Вы можете сделать простое копирование двоичных файлов на место, как указано в другом ответе, или вы можете использовать uupdate для сборки нового пакета debian из последнего источника. В принципе, это просто:

# apt-get build-dep ntp
# apt-get source ntp
# wget http://ntp.org/blah-src/ntp-version.tar.gz
# cd ntp-4.2.6.p5+dfsg
# uupdate ../ntp-version.tar.gz 
# cd ../ntp-version
# dpkg-buildpackage -uc -us -nc 
# dpkg -i ../ntp*.deb
9
28.05.2018, 10:14
4 ответа

returnrealiza un retorno explícito desde una función de shell o "punto script" (un script de origen ). Si returnno se ejecuta,se realiza un retorno implícito al final de la función de shell o script de puntos.

Si returnse ejecuta sin parámetro, es equivalente a devolver el estado de salida del último comando ejecutado.

Así es como funciona returnen todos los shells POSIX.

Por ejemplo,

gmx () {
  echo 'foo'
  return "$?"
}

es por lo tanto equivalente a

gmx () {
  echo 'foo'
  return
}

que es lo mismo que

gmx () {
  echo 'foo'
}

En general, es muy raro que necesite usar $?. Realmente solo es necesario si necesita guardarlo para uso futuro, por ejemplo, si necesita investigar su valor varias veces (, en cuyo caso asignaría su valor a una variable y realizaría una serie de pruebas en esa variable ).

16
27.01.2020, 20:05

De la página del manual bash(1):

When executed, the exit status of a function is the exit status of the last command executed in the body.

9
27.01.2020, 20:05

Solo agregaré algunas notas de precaución a las respuestas ya proporcionadas:

  • Aunque returntiene un significado muy especial para el shell, desde el punto de vista de la sintaxis, es un comando interno del shell y una declaración de retorno se analiza como cualquier otro comando simple. Entonces, eso significa que, como en el argumento de cualquier otro comando, $?cuando no está entrecomillado, estaría sujeto a split+glob

    Entonces necesitas citar eso $?para evitarlo:

    return "$?"
    
  • returngeneralmente no acepta ninguna opción(ksh93's acepta el habitual --help, --man, --author... aunque ). El único argumento que espera (opcional )es el código de retorno. El rango de códigos de retorno aceptados varía de shell a shell, y si algún valor fuera de 0..255 se refleja correctamente en $?también varía de shell a shell. Consulte ¿Código de salida predeterminado cuando finaliza el proceso? para obtener detalles al respecto.

    La mayoría de los shells aceptan números negativos (después de todo, el argumento pasado a la llamada del sistema _exit()/ exitgroup()es un int, por lo que con valores que abarcan al menos -2 31 ] a 2 31-1, por lo que solo tiene sentido que los shells acepten el mismo rango para sus funciones ).

    La mayoría de los proyectiles usan waitpid()y compañía. API para recuperar ese estado de salida, sin embargo, en cuyo caso, se trunca a un número entre 0 y 255 cuando almacenó en $?. Aunque invocar una función no implica generar un proceso y usar waitpid()para recuperar su estado de salida, ya que todo se hace en el mismo proceso, muchos shells también imitan ese comportamiento waitpid()al invocar funciones. Lo que significa que incluso si llamas a returncon un valor negativo, $?contendrá un número positivo.

    Ahora, entre aquellos shells cuyo returnacepta números negativos (ksh88, ksh93, bash, zsh, pdksh y derivados que no sean mksh, yash ),hay algunos (pdksh y yash )que necesitan que se escriba como return -- -123, de lo contrario, -123se toma como tres -1, -2, -3opciones no válidas.

    Como pdksh y sus derivados (como OpenBSD shoposh)conservan el número negativo en $?, eso significa que hacer return "$?"fallaría cuando $?contiene un número negativo (que sucedería cuando el último comando de ejecución fuera una función que devolviera un número negativo ).

    Entonces return -- "$?"sería mejor en esos caparazones. Sin embargo, tenga en cuenta que, si bien es compatible con la mayoría de los shells, esa sintaxis no es POSIX y, en la práctica, no es compatible con mkshy derivados de ash.

    Entonces, para resumir, con shells basados ​​en pdksh -, puede usar números negativos en los argumentos de las funciones, pero si lo hace, return "$@"no funcionará. En otros shells, return "$@"funcionará y debe evitar usar números negativos (o números fuera de 0..255 )como argumentos para return.

  • En todos los shells que conozco, llamar a returndesde dentro de un subshell que se ejecuta dentro de una función hará que el subshell salga (con el estado de salida proporcionado, si lo hay, o el del último comando ejecutado ), pero de lo contrario, no me causará un retorno de la función (, no está claro si POSIX le brinda esa garantía, algunos argumentan que exitdebería usarse en lugar de subcapas de salida dentro de las funciones ). Por ejemplo

    f() {
      (return 3)
      echo "still inside f. Exit status: $?"
    }
    f
    echo "f exit status: $?"
    

    generará:

    still inside f. Exit status: 3
    f exit status: 0
    
3
27.01.2020, 20:05

Sí, el valor de retorno implícito de una función es el estado de salida del último comando ejecutado . Eso también es cierto en cualquier punto de cualquier script de shell. En cualquier punto de la secuencia de ejecución del script, el estado de salida actual es el estado de salida del último comando ejecutado. Incluso comando ejecutado como parte de una asignación de variable:var=$(exit 34). La diferencia con las funciones es que una función podría cambiar el estado de salida al final de la ejecución de la función.

La ​​forma alternativa de cambiar el "estado de salida actual" es iniciar un subshell y salir con cualquier estado de salida necesario:

$ $(exit 34)
$ echo "$?"
34

Y sí, el estado de salida expansión debe citarse:

$ IFS='123'
$ $(exit 34)
$ echo $?
4

A (exit 34)también funcionan.
Algunos pueden argumentar que una construcción más robusta debería ser $(return 34), y que una salida debería "salir" del script que se está ejecutando. Pero $(return 34)no funciona con ninguna versión de bash. Por lo tanto, no es portátil.

La forma más segura de establecer un estado de salida es usarlo ya que fue diseñado para trabajar, definir y returndesde una función:

exitstatus(){ return "${1:-"$?"}"; }

Entonces, al final de una función. es exactamente equivalente a tener nada o returno return "$?". El final de una función no necesita significar la "última línea de código de una función".

#!/bin/sh
exitstatus(){ a="${1:-"$?"}"; return "$a"; }
gmx(){
    if     [ "$1" = "one" ]; then
           printf 'foo ';
           exitstatus 78
           return "$?"
    elif   [ "$1" = "two" ]; then
           printf 'baz ';
           exitstatus 89
           return
    else
           printf 'baz ';
           exitstatus 90
    fi
}  

Imprimirá:

$./script
foo 78
baz 89
baz 90

El único uso práctico para "$?"es imprimir su valor:echo "$?"o almacenarlo en una variable (ya que es un valor efímero y cambia con cada comando ejecutado):exitstatus=$?(recuerda citar la variable en comandos como export EXITSTATUS="$?".

En el comando return, el rango válido de valores es generalmente de 0 a 255, pero tenga en cuenta que algunos shells utilizan los valores de 126 + npara indicar un estado de salida especial, por lo tanto,la recomendación general es usar 0 -125.

0
27.01.2020, 20:05

Теги

Похожие вопросы