Estoy tratando de escribir un script de shell que esperará a que aparezca un archivo en el /tmpdirectorio llamado sleep.txty 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,openla secuencia de comandos solo está programada para su ejecución cuando/tmpse 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
openevento para registrar tambiéntouch /tmp/sleep.txtcuando 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?inotifywaites 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.txten 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
whilecircuito:fuente
sleepes 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
inotifywaitenfoques basados hasta ahora dados:sleep.txtarchivo creado primero como un nombre temporal y luego renombrado asleep.txt. Uno necesita coincidir paramoved_toeventos además decreatesleep.txtse ha creado uno. ¿Qué pasa sifoo\nsleep.txt\nbarse ha creado un archivo, por ejemplo?inotifywaitse haya iniciado e instalado el reloj? Luegoinotifywaitesperarí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.inotifywaitejecució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.txten el directorio actual.(por lo que haría uncd /tmp || exitantes en su ejemplo). El directorio actual nunca cambia, por lo que cuando esa línea de tubería regresa con éxito, sesleep.txtcrea un directorio en el directorio actual.Por supuesto, puede reemplazarlo
.con el/tmpanterior, pero mientras seinotifywaitestá ejecutando,/tmppodrí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.txtque ha sido creado pero un/new-name-for-the-original-tmp/sleep.txten su lugar. También se/tmppodría haber creado un nuevo directorio en el intervalo y ese no se vería, por lo que unosleep.txtcreado 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
$directoryToPutSleepFileEl archivo que colocará
$directoryToPutSleepFilepuede llamarse sleep.txt awake.txt, lo que sea. En el momento en que se cree un archivo dentro de$directoryToPutSleepFilesu script, continuará más allá de lainotifywaitdeclaración.fuente
sleep.txtque se cree entre dos invocaciones de inotifywait.sleep.txtse crea un archivo llamado . Intente, por ejemplotouch /tmp/foo /tmp/sleep.txt, luego una instancia deinotifywaitreportaráfooy 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