Estoy tratando de escribir un script de shell que esperará a que aparezca un archivo en el /tmp
directorio llamado sleep.txt
y una vez que se encuentre, el programa cesará, de lo contrario, quiero que el programa esté en estado de suspensión (suspendido) hasta que se encuentre el archivo . Ahora, supongo que usaré un comando de prueba. Entonces, algo como
(if [ -f "/tmp/sleep.txt" ];
then stop
else sleep.)
¡Soy nuevo en escribir script de shell y cualquier ayuda es muy apreciada!
shell-script
files
Mo Gainz
fuente
fuente
$MAILPATH
.Respuestas:
En Linux, puede usar el subsistema de kernel inotify para esperar eficientemente la aparición de un archivo en un directorio:
(suponiendo Bash para la
<()
sintaxis de redirección de salida)La ventaja de este enfoque en comparación con el sondeo de intervalo de tiempo fijo como en
es que el kernel duerme más. Con una especificación de evento inotify como
create,open
la secuencia de comandos solo está programada para su ejecución cuando/tmp
se crea o abre un archivo debajo . Con el sondeo de intervalo de tiempo fijo desperdicia ciclos de CPU por cada incremento de tiempo.Incluí el
open
evento para registrar tambiéntouch /tmp/sleep.txt
cuando el archivo ya existe.fuente
inotifywait -e create,open --format '%f' --quiet /tmp/sleep.txt --monitor > /dev/null ; # continues once /tmp/sleep.txt is created/opened
?inotifywait
es en sí mismo un ciclo while y genera una línea cada vez que se abre / crea el archivo. Por lo tanto, necesita que el bucle while se rompa cuando se cambia.sleep.txt
en algún momento. Por lo tanto, no hay condición de carrera. La pregunta no contiene nada que sugiera un escenario que tenga en mente.Simplemente ponga su prueba en el
while
circuito:fuente
sleep
es el número de segundos que debe esperar en cada iteración; puede cambiar eso según sus necesidades.Hay algunos problemas con algunos de los
inotifywait
enfoques basados hasta ahora dados:sleep.txt
archivo creado primero como un nombre temporal y luego renombrado asleep.txt
. Uno necesita coincidir paramoved_to
eventos además decreate
sleep.txt
se ha creado uno. ¿Qué pasa sifoo\nsleep.txt\nbar
se ha creado un archivo, por ejemplo?inotifywait
se haya iniciado e instalado el reloj? Luegoinotifywait
esperaría para siempre un archivo que ya está aquí. Debería asegurarse de que el archivo ya no esté allí después de instalar el reloj.inotifywait
ejecución (al menos hasta que se crea otro archivo) después de que se haya encontrado el archivo.Para abordarlos, podría hacer:
Tenga en cuenta que estamos esperando la creación
sleep.txt
en el directorio actual.
(por lo que haría uncd /tmp || exit
antes en su ejemplo). El directorio actual nunca cambia, por lo que cuando esa línea de tubería regresa con éxito, sesleep.txt
crea un directorio en el directorio actual.Por supuesto, puede reemplazarlo
.
con el/tmp
anterior, pero mientras seinotifywait
está ejecutando,/tmp
podría haber cambiado de nombre varias veces (lo que es improbable/tmp
, pero algo a tener en cuenta en el caso general) o un nuevo sistema de archivos montado en él, por lo que cuando la tubería regrese, puede que no ser un/tmp/sleep.txt
que ha sido creado pero un/new-name-for-the-original-tmp/sleep.txt
en su lugar. También se/tmp
podría haber creado un nuevo directorio en el intervalo y ese no se vería, por lo que unosleep.txt
creado allí no se detectaría.fuente
La respuesta aceptada realmente funciona (gracias maxschlepzig) pero deja el monitoreo de inotifywait en segundo plano hasta que se cierra el script. La única respuesta que coincide exactamente con sus requisitos (es decir, esperar a que se muestre sleep.txt dentro de / tmp) parece ser la de Stephane, si el directorio a ser monitoreado por inotifywait cambia de punto (.) A '/ tmp'.
Sin embargo, si está dispuesto a usar un directorio temporal SOLAMENTE para colocar su bandera sleep.txt y puede apostar a que nadie más colocará ningún archivo en ese directorio, solo pedirle a inotifywait que vea este directorio para crear archivos sería suficiente:
1er paso: crea el directorio que monitorearás:
2do paso: asegúrese de que el directorio esté realmente allí
3er paso: espere hasta que CUALQUIER archivo aparezca dentro
$directoryToPutSleepFile
El archivo que colocará
$directoryToPutSleepFile
puede llamarse sleep.txt awake.txt, lo que sea. En el momento en que se cree un archivo dentro de$directoryToPutSleepFile
su script, continuará más allá de lainotifywait
declaración.fuente
sleep.txt
que se cree entre dos invocaciones de inotifywait.sleep.txt
se crea un archivo llamado . Intente, por ejemplotouch /tmp/foo /tmp/sleep.txt
, luego una instancia deinotifywait
reportaráfoo
y saldrá , y para cuando se inicie el siguiente inotifywait, el sleep.txt ya habrá estado allí por lo que inotifywait no detectará su creación.en general, es bastante difícil hacer algo más que el simple test / sleep loop confiable. El principal problema es que la prueba se ejecutará con la creación del archivo; a menos que se repita la prueba, se puede perder el evento de creación. Esta es, de lejos, su mejor apuesta en la mayoría de los casos en los que estaría utilizando Shell para comenzar:
Si encuentra que esto es insuficiente debido a problemas de rendimiento, entonces usar Shell probablemente no sea una gran idea en primer lugar.
fuente
Basado en la respuesta aceptada de maxschlepzig (y una idea de la respuesta aceptada en /superuser/270529/monitoring-a-file-until-a-string-is-found ) Propongo lo siguiente mejorado ( en mi opinión) respuesta que también puede funcionar con tiempo de espera:
En caso de que el archivo no se cree / abra dentro del tiempo de espera dado, el estado de salida es 124 (según la documentación de tiempo de espera (página del manual)). En caso de que se cree / abra, el estado de salida es 0 (éxito).
Sí, inotifywait se ejecuta en un sub-shell de esta manera y ese sub-shell solo terminará de ejecutarse cuando se agote el tiempo de espera o cuando salga el script principal (lo que ocurra primero).
fuente