
Este script falla a veces y otras veces tiene éxito (una situación muy molesta):
#!/bin/bash
set -Eeuxo pipefail
test_dir="$(mktemp -d)"
touch "$test_dir/file"{001..312}
latest_file="$(find $test_dir -type f | sort -r | head -n1)"
echo $latest_file
Cuando tiene éxito, registra algo como esto:
++ mktemp -d
+ test_dir=/tmp/tmp.yWelcpBYB7
+ touch /tmp/tmp.yWelcpBYB7/file001 /tmp/tmp.yWelcpBYB7/file002 ... /tmp/tmp.yWelcpBYB7/file312
++ find /tmp/tmp.yWelcpBYB7 -type f
++ head -n1
++ sort -r
+ latest_file=/tmp/tmp.yWelcpBYB7/file312
+ echo /tmp/tmp.yWelcpBYB7/file312
/tmp/tmp.yWelcpBYB7/file312
Cuando falla, registra algo como esto:
++ mktemp -d
+ test_dir=/tmp/tmp.VzTqmgpZyG
+ touch /tmp/tmp.VzTqmgpZyG/file001 /tmp/tmp.VzTqmgpZyG/file002 ... /tmp/tmp.VzTqmgpZyG/file312
++ find /tmp/tmp.VzTqmgpZyG -type f
++ sort -r
++ head -n1
+ latest_file=/tmp/tmp.VzTqmgpZyG/file312
Observe que la echo $latest_file
línea esnoejecutado aquí aunque aparece en xtrace
No puedo ejecutar correctamente si uso 10.000 archivos, por lo que sospecho que tiene algo que ver concabezaparadaencontrartemprano.
#!/bin/bash
set -Eeuxo pipefail
test_dir="$(mktemp -d)"
touch "$test_dir/file"{0000..9999}
latest_file="$(find $test_dir -type f | sort -r | head -n1)"
echo $latest_file
Si suprimo la parada por error (usandoconjunto +e), tiene éxito:
#!/bin/bash
set -Eeuxo pipefail
test_dir="$(mktemp -d)"
touch "$test_dir/file"{0000..9999}
set +e
latest_file="$(find $test_dir -type f | sort -r | head -n1)"
set -e
echo $latest_file
¿Por qué este script no registra de manera confiable el archivo más reciente?
Respuesta1
El problema es el -e
. ¿Por qué? -e
hace que bash aborte en caso de que un proceso salga con un código de salida distinto de cero (las reglas completas son un poco más complicadas). Si hay una tubería, solo cuenta el último comando.
Crea head -n1
una situación de error, internamente, porque tiene que romper la tubería (puede comprobarlo con strace
) para ignorar el resto de la salida sort
.
Entonces, para que su script funcione de manera confiable -e
, puede agregar a cat
al final de la tubería. head
Seguirá rompiendo la tubería, pero como ya no es el último comando, no será tenido en cuenta por -e
. cat
es una operación no operativa para la tubería:
#!/bin/bash
set -Eeuxo pipefail
test_dir="$(mktemp -d)"
touch "$test_dir/file"{0000..9999}
latest_file="$(find $test_dir -type f | sort -r | head -n1 | cat)"
echo $latest_file
por favor, compruebe¿Por qué set -e (o set -o errexit o trap ERR) no hace lo que esperaba?saber por qué -e
es una característica tan inestable y el tipo de problemas que puede provocar. Hay muchos ejemplos al final. Mi favorito:
#!/bin/bash
set -e
foo=$(expr 1 - 1)
echo survived
Va anoimprimirsobrevivió, esa línea no se ejecutará. Pero, si lo hubieras hecho foo=$(expr 2 - 1)
, ¡ echo
sería ejecutado!
Sería mejor que implementara su propia verificación de errores, -e
no es la mejor solución que existe.