2010-05-18 28 views
536

En una secuencia de comandos de shell ¿cómo echo todos los comandos de shell llamados y expandir los nombres de variables? Por ejemplo, dada la siguiente línea:En una secuencia de comandos de shell: comandos echo shell como se ejecutan

ls $DIRNAME 

Me gustaría que la secuencia de comandos para ejecutar el comando y visualizar la siguiente

ls /full/path/to/some/dir 

El propósito es guardar un registro de todos los comandos de shell llamado y su argumentos. Tal vez hay una mejor forma de generar un tal log?

Respuesta

598

set -x o set -o xtrace expande las variables e imprime un pequeño signo + antes de la línea.

set -v o set -o verbose no expande las variables antes de imprimir.

Utilice set +x y set +v para desactivar la configuración anterior.

En la primera línea del script, uno puede poner #!/bin/sh -x (o -v) para tener el mismo efecto que set -x (o -v) más tarde en el guión.

Lo anterior también funciona con /bin/sh.

http://www.faqs.org/docs/abs/HTML/options.html

$ cat shl 
#!/bin/bash                  

DIR=/tmp/so 
ls $DIR 

$ bash -x shl 
+ DIR=/tmp/so 
+ ls /tmp/so 
$ 
224

set -x le dará lo que quiere.

Aquí es un script de shell ejemplo para demostrar:

#!/bin/bash 
set -x #echo on 

ls $PWD 

Esto expande todas las variables e imprime los comandos completos antes de la salida del comando.

de salida:

+ ls /home/user/ 
file1.txt file2.txt 
+18

El uso de la palabra "prolija" de esa manera no se logra nada. Puede hacer 'set -o verbose' o' set -v' (solo "verbose") o 'set -o xtrace' o' set -x' (solo "xtrace") o 'set -xv' (ambos) o 'set -o xtrace -o verbose' (ambos). –

+0

esto funciona bien, pero tenga en cuenta que el "detallado" sobrescribe $ 1 – JasonS

+0

@jasonS * bien. Pero sí, yo no había pensado en eso, bueno – Wyatt8740

67

También puede cambiar esto para líneas de selección en la secuencia de comandos envolviéndolos en set -x y set +x por ejemplo,

#!/bin/bash 
... 
if [[ ! -e $OUT_FILE ]]; 
then 
    echo "grabbing $URL" 
    set -x 
    curl --fail --noproxy $SERV -s -S $URL -o $OUT_FILE 
    set +x 
fi 
27

Otra opción es poner "-x" en la parte superior de la secuencia de comandos en lugar de en la línea de comandos: (Rep. Insuficiente para comentar respuesta elegida)

$ cat ./server 
#!/bin/bash -x 
ssh [email protected] 

$ ./server 
+ ssh [email protected] 
[email protected]'s password: ^C 
$ 

+0

Tenga en cuenta que esto no parece funcionar exactamente igual entre './MyScript' y' bash myScript'. Aún es bueno señalarlo, gracias. – altendky

3

para zsh eco

setopt VERBOSE 

y para la depuración

respuesta
setopt XTRACE 
34

de shuckc de eco líneas de selección tiene algunas desventajas: se termina con la set +x siguiente comando se hizo eco así, y se pierde la posibilidad de probar el código de salida con $? ya que se sobreescribe por el set +x.

Otra opción es ejecutar el comando en un subnivel:

echo "getting URL..." 
(set -x ; curl -s --fail $URL -o $OUTFILE) 

if [ $? -eq 0 ] ; then 
    echo "curl failed" 
    exit 1 
fi 

que le dará una salida como:

getting URL... 
+ curl -s --fail http://example.com/missing -o /tmp/example 
curl failed 

Esto hace incurrir en la sobrecarga de crear un nuevo subnivel para el comando, aunque.

+6

Buena forma de evitar la salida '++ set + x'. –

+2

Mejor aún: reemplace 'if [$? -eq 0] 'con' if (set -x; COMMAND) '. –

14

Escriba "bash -x" en la línea de comando antes del nombre del script bash. Por ejemplo, para ejecutar foo.sh, Tipo:

bash -x foo.sh 
55

utilizo una función de hacer eco a continuación, ejecute el comando

#!/bin/bash 
#function to display commands 
exe() { echo "\$ [email protected]" ; "[email protected]" ; } 

exe echo hello world 

que da salida a

$ echo hello world 
hello world 

Editar:

Para obtener comandos más complicados, tuberías, etc. puede usar eval:

#!/bin/bash 
#function to display commands 
exe() { echo "\$ ${@/eval/}" ; "[email protected]" ; } 

exe eval "echo 'Hello World' | cut -d ' ' -f1" 

que da salida a

$ echo 'Hello World' | cut -d ' ' -f1 
Hello 
+0

No hay muchos votos para esta respuesta. ¿Hay alguna razón por la cual es una mala idea? Funcionó para mí, y parece ser exactamente lo que estoy buscando ... – fru1tbat

+1

Esta es la mejor respuesta si no quiere que se impriman todos los comandos. Evita la salida '++ set + x' cuando está desactivado, además de verse más limpio. Sin embargo, para una sola declaración o dos, la respuesta de Bhassel utilizando una subshell es la más conveniente. –

+0

Esto es lo que estoy buscando! No 'set + x', afecta a todos los comandos, ¡que es demasiado! – Hlung

2

Para csh y tcsh, puede set verbose o set echo (o incluso se puede establecer tanto, pero puede dar lugar a cierta duplicación mayor parte del tiempo).

La opción verbose imprime prácticamente la expresión de shell exacta que escribe.

La opción echo es más indicativa de lo que se ejecutará a través del desove.


http://www.tcsh.org/tcsh.html/Special_shell_variables.html#verbose

http://www.tcsh.org/tcsh.html/Special_shell_variables.html#echo


Special shell variables

verbose If set, causes the words of each command to be printed, after history substitution (if any). Set by the -v command line option.

echo If set, each command with its arguments is echoed just before it is executed. For non-builtin commands all expansions occur before echoing. Builtin commands are echoed before command and filename substitution, because these substitutions are then done selectively. Set by the -x command line option.

1

Para permitir la repetición de comandos compuestos, uso eval más la función exe de Soth para hacer eco y luego ejecutar el comando. Esto es útil para comandos canalizados que de lo contrario solo mostrarían ninguno o solo la parte inicial del comando canalizado.

Sin eval:

exe() { echo "\$ [email protected]" ; "[email protected]" ; } 
exe ls -F | grep *.txt 

Salidas:

$ 
file.txt 

Con eval:

exe() { echo "\$ [email protected]" ; "[email protected]" ; } 
exe eval 'ls -F | grep *.txt' 

que da salida a

$ exe eval 'ls -F | grep *.txt' 
file.txt 
14

Según TLDP 's Bash Guide for Beginners: Chapter 2. Writing and debugging scripts

2.3.1. Depuración en todo el guión

$ bash -x script1.sh 

...

Ahora hay un depurador de pleno derecho de Bash, disponible en SourceForge. Estas funciones de depuración están disponibles en la mayoría de las versiones modernas de Bash, a partir de 3.x.

2.3.2. La depuración en la parte (s) del guión

set -x   # activate debugging from here 
w 
set +x   # stop debugging from here 

...

Tabla 2-1. Descripción general del conjunto de opciones de depuración

Short | Long notation | Result 
-------+---------------+-------------------------------------------------------------- 
set -f | set -o noglob | Disable file name generation using metacharacters (globbing). 
set -v | set -o verbose| Prints shell input lines as they are read. 
set -x | set -o xtrace | Print command traces before executing command. 

...

Alternativamente, estos modos se puede especificar en el propio script, por añadiendo las opciones que desee en la primera declaración del shell de línea. opciones se pueden combinar, como suele ser el caso de los comandos de UNIX:

#!/bin/bash -xv 
1
$ cat exampleScript.sh 
#!/bin/bash 
name="karthik"; 
echo $name; 

bash -x exampleScript.sh 

de salida es el siguiente:

enter image description here

4

Alguien anterior publicado:

#!/bin/bash 
#function to display commands 
exe() { echo "\$ [email protected]" ; "[email protected]" ; } 

y esto l Ook es prometedor, pero no puedo por mi propia vida descubrir qué hace. Busqué en Google y busqué en la página de hombre bash para "\ $" y "$ @", y encontré absolutamente nada.

Entiendo que se está creando una función, llamada "exec()". Entiendo que los corchetes marcan el comienzo y el final de la función.Creo que entiendo que el punto y coma indica un "retorno difícil" entre un comando de varias líneas, de modo que "{echo" \ $ $ @ "; ps }' Se convierte, en esencia:

{ 
echo "\$ [email protected]" 
"[email protected]" 

} 

¿Puede alguien darme una breve explicación, o dónde encontrar esta información, ya que, obviamente, mi google-fu me está fallando?

(Sin tener que empezar una nueva pregunta en un hilo viejo, mi objetivo es redirigir la salida a un archivo. El método "set -x; [commands]; set + x" me funcionaría adecuadamente, pero no puedo entender cómo hacer eco de los resultados en un archivo en lugar de en la pantalla, así que estaba tratando de entender este otro método con la esperanza de que pudiera usarme una comprensión muy pobre de la redirección/pipes/tee/etc para hacer lo mismo cosa.)

Gracias!

de editar posteriormente:

Con algunos retoques, creo que lo he descubierto. Aquí está mi código equivalente para lo que estoy necesitando:

SCRIPT_LOG="\home\buddy\logfile.txt" 
exe() { 
    params="[email protected]"      # Put all of the command-line into "params" 
    printf "%s\t$params" "$(date)" >> "$SCRIPT_LOG" # Print the command to the log file 
    $params       # Execute the command 
} 

exe rm -rf /Library/LaunchAgents/offendingfile 
exe rm -rf /Library/LaunchAgents/secondoffendingfile 

Los resultados en el logfile.txt ser algo como:

Tue Jun 7 16:59:57 CDT 2016 rm -rf /Library/LaunchAgents/offendingfile 
Tue Jun 7 16:59:57 CDT 2016 rm -rf /Library/LaunchAgents/secondoffendingfile 

Justo lo que necesitaba. ¡Gracias!

+0

Creo que lo descubrí. Aquí está mi código equivalente para lo que estoy necesitando: exe ​​() { params = "$ @" \t \t \t \t \t \t # Ponga toda la línea de comandos de "params" printf "% s \ t $ params " "$ (fecha)" >> "$ SCRIPT_LOG" \t # mostrar el comando al archivo de registro $ params \t \t \t \t \t \t \t # ejecutar el comando} \t exe ​​rm-rf/Library/LaunchAgents/com .carbonite.launchd.carbonitealerts.plist \t exe ​​rm -rf /Library/LaunchAgents/com.carbonite.launchd.carbonitestatus.plist – DebianFanatic

+0

Necesidades \ n para romper la línea en 'printf"% s \ t $ params "" $ (date) ">>" $ SCRIPT_LOG "' – user3762200

3

Puede ejecutar una secuencia de comandos bash en modo de depuración con la opción -x.
Esto hará eco de todos los comandos.

bash -x example_script.sh 

# Console output 
+ cd /home/user 
+ mv text.txt mytext.txt 


Usted puede también guardar la opción -x en el script. Simplemente especifique la opción -x en el shebang.

######## example_script.sh ################### 
#!/bin/bash -x 

cd /home/user 
mv text.txt mytext.txt 

############################################## 

./example_script.sh 

# Console output 
+ cd /home/user 
+ mv text.txt mytext.txt 



Cuestiones relacionadas