Tengo un script bash con varias declaraciones if basadas en argumentos de línea de comando que paso al llamarlo. Tener algún tipo de salida sobre qué comandos se están ejecutando es útil para confirmar el flujo a través de todas esas declaraciones if, pero mi solución actual me está dando demasiada información.
Usando set -v
en el guión fue algo útil para ver los comandos se envían a la pantalla a medida que se ejecutan en el guión, sin embargo llego demasiado comandos. Es casi como una copia completa del guión.
Quiero una salida que muestre qué comandos se están ejecutando, pero no quiero ver comentarios, nuevas líneas, expresiones en declaraciones if, etc.
¿Hay alguna manera de que pueda pasar toda la salida posible generada por la opción -v a través de una expresión regular primero antes de imprimirla? ¿O alguna otra solución para hacer que bash solo muestre comandos de un cierto "tipo" (por ejemplo, que están usando ejecutables y no solo declaraciones específicas de bash, comentarios, etc.?)
[1] /programming/257616/sudo-changes-path-why fue bastante útil en esto y es donde obtuve la sugerencia para el set -v
uso.
Editar :
Un script similar (pero no idéntico) al que estoy ejecutando:
#!/bin/bash
#get verbose command output
set -v
env=$1
if [ "$env" == "dev" ]; then
python ascript.py
fi
if [ "$env" == "prod" ]; then
#launching in prod will most likely fail if not run as root. Warn user if not running as root.
if [ $EUID -ne 0 ]; then
echo "It doesn't look like you're running me as root. This probably won't work. Press any key to continue." > /dev/stderr
read input
fi
#"stop" any existing nginx processes
pkill -f nginx
nginx -c `pwd`/conf/artfndr_nginx.conf
fi
Solo quiero 2 conjuntos posibles de líneas de salida de este script. El primero:
python ascript.py
El segundo:
pkill -f nginx
nginx -c /some/current/directory/conf/artfndr_nginx.conf
fuente
set -v
salida desea y cuáles no.Respuestas:
Cuando escribo scripts de bash más complejos, utilizo una pequeña función para ejecutar comandos que también imprimirán los comandos ejecutados en un archivo de registro:
Luego, en mi script, ejecuto comandos como este:
Si no desea que se imprima un comando, simplemente ejecútelo normalmente.
Puede establecerlo
$LOG
en un nombre de archivo o simplemente eliminarlo e imprimirlo en stdout o stderr.fuente
v python ascript.py
sin tener que encerrarse entre comillas y perder el resaltado del código vimeval ..... || ok=1
: establecerá ok en "1" solo cuando "eval ..." falle? ¿Quizás quisiste decir "&&"? Y si quiso decir eso, agregue un "ok = 0" antes de la línea de evaluación, para que sea "restablecer" cada vez. ¿O simplemente cambia el nombre de "ok" a "error"? Parece que eso es lo que se quiso decir aquí. Así que al final:eval "$@" 2>> "$LOG" && error=0 || error=1
ok
variable que detendrá el script si falla algún comando. Como eso no era relevante aquí, lo eliminé pero olvidé eliminarlo|| ok=1
. Gracias, arreglado ahora."
enunciado que rodea la evaluación, porque el comando ya está rodeado por"
sUse un sub-shell, es decir:
Por ejemplo:
huellas dactilares
fuente
set -x; cmd; set +x
por varias razones. Primero, no se reiniciaset -x
en caso de que haya estado encendido antes. En segundo lugar, la terminación de la secuencia de comandos en el interior no hace que las trampas se ejecuten con configuraciones detalladas activadas.He visto métodos similares a los de @ terdon. Es el comienzo de lo que los lenguajes de programación de nivel superior llaman registradores y ofrecen como bibliotecas completas, como log4J (Java), log4Perl (Perl), etc.
Puede obtener algo similar usando
set -x
en Bash como ha mencionado, pero puede usarlo para activar la depuración solo un subconjunto de comandos envolviendo bloques de código con ellos de esta manera.Ejemplos
Aquí hay un patrón de una línea que puede usar.
Puede envolverlos así para múltiples comandos en un script.
Log4Bash
La mayoría de las personas son ajenas pero Bash también tiene un log4 * también, Log4Bash . Si tiene necesidades más modestas, podría valer la pena configurarlo.
Ejemplos
Aquí hay algunos ejemplos del uso de log4bash.
Log4sh
Si quieres lo que clasificaría como más de la potencia total de un marco log4 *, entonces probaría Log4sh .
extracto
Log4sh admite varios shells, no solo Bash.
También se ha probado en varios sistemas operativos, no solo en Linux.
El uso de un marco log4 * llevará algún tiempo para aprender, pero vale la pena si tiene necesidades más exigentes de su registro. Log4sh utiliza un archivo de configuración donde puede definir los apéndices y controlar el formato de la salida que aparecerá.
Ejemplo
Ahora cuando lo ejecuto:
NOTA: Lo anterior configura el apéndice como parte del código. Si lo desea, puede extraerlo en su propio archivo,
log4sh.properties
etc.Consulte la excelente documentación de Log4sh si necesita más detalles.
fuente
set
comandos que necesitaría presentar, alternando comentarios, etc., por lo que solo tener una función en la parte superior de mi script, con una llamada de función de un solo carácter antepuesta a Todas las líneas "importantes" en el guión me parecían más ordenadas por ahora. (carácter único porque la función tiene un nombre de carácter único)echo
mi propia funciónmecho
y luego pasar un cambio al programa llamado-v
detallado cuando quiero apagar las cosas. También puedo controlarlo con un interruptor de segundo argumento que especifica el nombre de la función, por lo que tengo 2 ejes para controlar el registro. Sin embargo, esta suele ser la puerta de entrada para querer log4bash.set -x
imprime los comandos a medida que se ejecutan. No imprime comentarios.set -x
es práctico para la depuración (a diferencia de loset -v
cual no es muy útil). Zsh tiene mejor salidaset -x
que bash, por ejemplo, muestra qué función se está ejecutando actualmente y el número de línea de origen.Podrías
trap
DEBUG
y luego probar laBASH_COMMAND
variable . Agregue esto a la parte superior del script:El código es legible; solo prueba si el primer argumento comienza con
python
opkill
, y lo imprime si ese es el caso. Y la trampa usaBASH_COMMAND
(que contiene el comando que se ejecutará) como primer argumento.Tenga en cuenta que si bien
case
usa globs, podría hacer lo mismo:Y usa expresiones regulares.
fuente
Esta es una versión revisada de la función ordenada de Steven Penny. Imprime sus argumentos en color y los cita según sea necesario. Úselo para repetir selectivamente los comandos que desea rastrear. Como se envían comillas, puede copiar líneas impresas y pegarlas en el terminal para volver a ejecutarlas inmediatamente mientras está depurando un script. Lea el primer comentario para saber qué he cambiado y por qué.
Ejemplo de uso con salida:
# xc echo "a b" "c'd" "'" '"' "fg" '' " " "" \# this line prints in green
echo 'a b' c\'d \' '"' fg '' ' ' '' '#' this line prints in green
a b c'd ' " fg # this line prints in green
La segunda línea de arriba se imprime en verde y se puede copiar y pegar para reproducir la tercera línea.
Más observaciones
El xc original de @ Steven-Penny es inteligente y se merece todos los créditos por ello. Sin embargo, noté algunos problemas, pero no pude comentar su publicación directamente porque no tengo suficiente reputación. Así que hice una edición sugerida a su publicación, pero los revisores rechazaron mi edición. Por lo tanto, recurrí a publicar mis comentarios como esta respuesta, aunque hubiera preferido poder editar la propia respuesta de Steve Penny.
Lo que cambié con la respuesta de Steven-Penny
Corregido: impresión de cadenas nulas, no se imprimieron. Se corrigió: las cadenas de impresión que incluyen
%
- causaron errores de sintaxis awk. Reemplazadofor (j in ...)
confor (j = 0, ...)
ya que el primero no garantiza el orden de la matriz de recorrido (que es dependiente de la implementación de awk). Se agregó 0 a los números octales para la portabilidad.Actualizar
Desde entonces, Steven Penny ha solucionado esos problemas en su respuesta, por lo que estas observaciones se quedan solo para el registro histórico de mi respuesta. Vea la sección de Comentarios para más detalles.
fuente
Puede utilizar la función de shell "sh_trace" de la biblioteca POSIX stdlib para imprimir el comando en color antes de ejecutarlo. Ejemplo:
Función subyacente de Awk:
fuente