traduccion - ¿Cómo hacer eco de los comandos de shell mientras se ejecutan?
shell usa (14)
En un script de shell, ¿cómo hago eco de todos los comandos de shell llamados y amplío cualquier nombre de variable? Por ejemplo, dada la siguiente línea:
ls $DIRNAME
Me gustaría que el script ejecute el comando y muestre lo siguiente
ls /full/path/to/some/dir
El propósito es guardar un registro de todos los comandos de shell llamados y sus argumentos. Tal vez hay una mejor manera de generar tal un registro?
Alguien arriba publicado:
#!/bin/bash
#function to display commands
exe() { echo "/$ $@" ; "$@" ; }
y esto parece prometedor, pero no puedo, por mi vida, descubrir lo que hace. Busqué en Google y busqué en la página man bash "/ $" y "$ @", y no encuentro absolutamente nada .
Entiendo que se está creando una función, llamada "exec ()". Entiendo que los rizos marcan el principio y el final de la función. Creo que entiendo que el punto y coma marca un "retorno difícil" entre un comando de varias líneas, por lo que ''{echo "/ $ $ @"; PS } ''se convierte, en esencia:
{
echo "/$ $@"
"$@"
}
¿Puede alguien darme una breve explicación o dónde encontrar esta información, ya que obviamente mi google-fu me está fallando?
(Sin querer iniciar una nueva pregunta en un hilo viejo, mi objetivo es redirigir la salida a un archivo. El método "set -x; [comandos]; set + x" funcionaría adecuadamente para mí, pero no puedo '' Averigué cómo hacer eco de los resultados en un archivo en lugar de en la pantalla, por lo que estaba tratando de entender este otro método con la esperanza de que no pudiera entenderme muy bien sobre la redirección / pipe / tee / etc para hacer lo mismo.)
¡Gracias!
DESPUÉS DE EDITAR:
Con algunos retoques, creo que lo descubrí. Aquí está mi código equivalente para lo que necesito:
SCRIPT_LOG="/home/buddy/logfile.txt"
exe () {
params="$@" # 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 se ven algo así 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!
De acuerdo con la Guía Bash para principiantes de TLDP : Capítulo 2. Escritura y depuración de scripts
2.3.1. Depuración de todo el script.
$ bash -x script1.sh
...
Ahora hay un depurador completo para 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. Depuración de parte (s) de la secuencia de comandos
set -x # activate debugging from here w set +x # stop debugging from here
...
Tabla 2-1. Descripción general de las opciones de depuración establecidas
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 pueden especificar en el propio script, agregando las opciones deseadas a la primera línea de declaración de shell. Las opciones se pueden combinar, como suele ser el caso con los comandos UNIX:
#!/bin/bash -xv
Escriba "bash -x" en la línea de comando antes del nombre del script bash. Por ejemplo, para ejecutar foo.sh, escriba:
bash -x foo.sh
La respuesta de shuckc para las líneas de selección de eco tiene algunas desventajas: ¿terminará con el siguiente comando set +x
y también perderá la capacidad de probar el código de salida con $?
ya que se sobrescribe con el set +x
.
Otra opción es ejecutar el comando en una subshell:
echo "getting URL..."
( set -x ; curl -s --fail $URL -o $OUTFILE )
if [ $? -eq 0 ] ; then
echo "curl failed"
exit 1
fi
lo que te dará salida como:
getting URL...
+ curl -s --fail http://example.com/missing -o /tmp/example
curl failed
Sin embargo, esto incurre en la sobrecarga de crear una nueva subshell para el comando.
Otra opción es colocar "-x" en la parte superior de su script en lugar de en la línea de comandos:
$ cat ./server
#!/bin/bash -x
ssh user@server
$ ./server
+ ssh user@server
user@server''s password: ^C
$
(Representante insuficiente para comentar la respuesta elegida).
Para csh
y tcsh
, puede set verbose
set echo
set verbose
o set echo
(o incluso puede configurar ambos, pero puede dar como resultado cierta duplicación la mayor parte del tiempo).
La opción verbose
imprime casi la expresión de shell exacta que escribe.
La opción de 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.
Para permitir que los comandos compuestos se repitan, uso la función exe
eval
más Soth para hacer eco y luego ejecutar el comando. Esto es útil para comandos canalizados que de otra manera solo mostrarían ninguno o solo la parte inicial del comando canalizado.
Sin eval:
exe() { echo "/$ $@" ; "$@" ; }
exe ls -F | grep *.txt
Salidas:
$
file.txt
Con eval:
exe() { echo "/$ $@" ; "$@" ; }
exe eval ''ls -F | grep *.txt''
Que salidas
$ exe eval ''ls -F | grep *.txt''
file.txt
Para zsh echo
setopt VERBOSE
y para la depuración
setopt XTRACE
Puede ejecutar un script de 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
También puede guardar la opción -x en el script . Solo especifica 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
También puede alternar esto para seleccionar líneas en su script 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
Utilizo una función para hacer eco y luego ejecutar el comando
#!/bin/bash
#function to display commands
exe() { echo "/$ $@" ; "$@" ; }
exe echo hello world
Que salidas
$ echo hello world
hello world
Editar:
Para tuberías de comandos más complicadas, etc. puedes usar eval:
#!/bin/bash
#function to display commands
exe() { echo "/$ ${@/eval/}" ; "$@" ; }
exe eval "echo ''Hello World'' | cut -d '' '' -f1"
Que salidas
$ echo ''Hello World'' | cut -d '' '' -f1
Hello
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.
Use set +x
y set +v
para desactivar la configuración anterior.
En la primera línea del script, se puede poner #!/bin/sh -x
(o -v
) para que tenga el mismo efecto que set -x
(o -v
) más adelante en el script.
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
$
set -x
te dará lo que quieras.
Aquí hay un ejemplo de script de shell 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.
salida:
+ ls /home/user/
file1.txt file2.txt