2010-08-03 24 views
59

¿Se puede editar un script de shell mientras se está ejecutando y los cambios afectan al script en ejecución?Editar script de shell mientras se está ejecutando

Tengo curiosidad sobre el caso específico de un script csh Tengo ese lote ejecuta un montón de diferentes sabores de construcción y se ejecuta toda la noche. Si se me ocurre algo a mitad de la operación, me gustaría ingresar y agregar comandos adicionales, o comentar los que no se ejecutaron.

Si no es posible, ¿hay algún mecanismo de shell o lote que me permita hacer esto?

Por supuesto que lo he probado, pero pasarán horas antes de que vea si funcionó o no, y tengo curiosidad sobre lo que está sucediendo o lo que no sucede detrás de escena.

+0

He visto dos resultados de la edición del archivo de script para un script en ejecución: 1) los cambios se ignoran como si se hubiera leído todo en la memoria o 2) el script se bloquea con un error como si hubiera leído parte de comando. No sé si eso depende del tamaño del guión. De cualquier manera, no lo intentaría. –

+0

En resumen: no, a menos que sea de autorreferencial/llamada, en cuyo caso el script principal seguiría siendo el anterior. – Wrikken

+0

Aquí hay dos preguntas importantes. 1) ¿Cómo puedo agregar comandos de forma correcta y segura a un script en ejecución? 2) Cuando modifico un script en ejecución, ¿qué pasará? –

Respuesta

-31

Las secuencias de comandos no funcionan de esa manera; la copia de ejecución es independiente del archivo fuente que está editando. La próxima vez que se ejecute el script, se basará en la versión guardada más recientemente del archivo fuente.

Podría ser aconsejable dividir este script en varios archivos y ejecutarlos individualmente. Esto reducirá el tiempo de ejecución a la falla. (es decir, divida el lote en uno de los scripts de compilación de sabor, ejecutándolos individualmente para ver cuál está causando el problema).

+1

He observado lo mismo. Cualquier lugar en la documentación bash (o csh o ksh) donde se menciona? – Xolve

+41

He observado lo contrario. Ejecutar scripts bash que se editan puede hacer que la secuencia de comandos en ejecución se cuelgue porque el archivo parece moverse en la posición del archivo de lectura del script de bash. –

+7

En mi experiencia en sistemas múltiples, la copia de ejecución NO es independiente del archivo de disco, es por eso que este problema es tan sorprendente e importante en la programación de scripts de shell. –

2

no tengo instalado CSH, pero

#!/bin/sh 
echo Waiting... 
sleep 60 
echo Change didn't happen 

Run que, editar rápidamente la última línea para leer

echo Change happened 

salida es

Waiting... 
/home/dave/tmp/change.sh: 4: Syntax error: Unterminated quoted string 

Hrmph.

Supongo que las ediciones de los scripts de shell no surtirán efecto hasta que se vuelvan a ejecutar.

+1

debe poner la cadena que desea mostrar entre comillas. – user1463308

+1

en realidad, demuestra que su editor no funciona de la manera que usted piensa. muchos, muchos editores (incluyendo vim, emacs) operan en un archivo "tmp", y no en un archivo en vivo. Intenta usar "echo 'echo uh oh' >> myshell.sh" en lugar de vi/emacs ... y mira a medida que saca las cosas nuevas. Peor aún ... ¡svn y rsync también editan de esta manera! –

+1

-1. Ese error no está relacionado con el archivo que se está editando: ¡se debe a que está utilizando un apóstrofo! Eso actúa como una comilla simple, causando el error. Pon toda la cadena entre comillas dobles e intenta de nuevo. –

-4

Por lo general, no es común editar el script mientras se está ejecutando. Todo lo que tiene que hacer es controlar sus operaciones. Use declaraciones if/else para verificar las condiciones. Si algo falla, haz esto, o hazlo. Ese es el camino a seguir.

+0

En realidad, se trata menos de las secuencias de comandos que de la modificación de la operación intermedia del trabajo por lotes. ES DECIR. dándome cuenta de que hay más que quiero compilar, o que no necesito ciertos trabajos que ya están en cola. – ack

+0

Si estrictamente * se agrega * a las secuencias de comandos, ¡entonces bash hará lo que esperas! –

0

que estoy oyendo no ... pero ¿qué pasa con un poco de indirección:

BatchRunner.sh

Command1.sh 
Command2.sh 

Command1.sh

runSomething 

Comando2. sh

runSomethingElse 

Entonces debería poder editar el contenido de cada archivo de comando antes de que BatchRunner lo haga ¿correcto?

O

Una versión más limpia tendría BatchRunner mirar a un solo archivo donde se haría de forma consecutiva carrera de una línea a la vez. Entonces deberías poder editar este segundo archivo mientras el primero se está ejecutando ¿verdad?

+0

Me pregunto si los carga en la memoria para ejecutarlos y un cambio no importa una vez que se inicia el proceso principal ... – Relic

1

Si todo esto está en una sola secuencia de comandos, entonces no funcionará. Sin embargo, si lo configura como una secuencia de comandos del controlador que llama a los subguiones, entonces es posible que pueda cambiar un subguión antes de invocarlo, o antes de que se vuelva a llamar si está realizando un bucle, y en ese caso creo que esos cambios se reflejaría en la ejecución.

13

romper su guión en funciones, y cada vez que se invoca una función que source desde un archivo separado. Luego, podría editar los archivos en cualquier momento y su secuencia de comandos activada detectará los cambios la próxima vez que se obtengan.

foo() { 
    source foo.sh 
} 
foo 
+0

He estado usando esta técnica de manera efectiva por un tiempo para actualizar mis scripts de compilación de larga ejecución mientras estan corriendo. Me encantaría aprender una técnica para hacer que el archivo actual se lea hasta el final del archivo, para que no tenga que tener dos archivos para implementar cada script de shell. –

30

[editar] Véase también this answer, section 3 para las soluciones.

Se Cómo afecta, al menos fiesta en mi entorno, pero en manera muy desagradable. Vea estos códigos. En primer lugar a.sh:

#!/bin/sh 

echo "First echo" 
read y 

echo "$y" 

echo "That's all." 

b.sh:

#!/bin/sh 

echo "First echo" 
read y 

echo "Inserted" 

echo "$y" 

# echo "That's all." 

Haz

$ cp a.sh run.sh 
$ ./run.sh 
$ # open another terminal 
$ cp b.sh run.sh # while 'read' is in effect 
$ # Then type "hello." 

En mi caso, la salida es siempre:

hello 
hello 
That's all. 
That's all.

Ésta es impredecible, por lo tanto peligroso. Vea this answer, section 3 para soluciones.

[agregado] El comportamiento exacto depende de un solo salto de línea extra, y quizás también en el sabor de Unix, sistema de ficheros, etc. Si simplemente quieres ver algunas influencias, sólo tiene que añadir "eco foo/bar" a b.sh antes y/o después de la línea "leer".

+2

Mh, no veo el afecto. ¿Me estoy perdiendo de algo? –

+0

El comportamiento exacto depende de _una nueva línea_ adicional, y tal vez también en el sabor de Unix, sistema de archivos, etc., pensado que no es seguro en al. Si simplemente desea ver las influencias, simplemente aumente 'b.sh' agregando 10 líneas de eco foo/bar/baz. La esencia de las respuestas de dave4220 y de mí es que el efecto no es fácil de predecir. (Por cierto, el sustantivo "afecto" significa "amor" =) –

+0

sí, está muy roto. tengo una solución (abajo). lo que es aún más peligroso es svn/rsync/git updates –

21

Prueba esto ... crear un archivo llamado "bash-is-odd.sh":

#!/bin/bash 
echo "echo yes i do odd things" >> bash-is-odd.sh 

Eso demuestra que la fiesta es, de hecho, la interpretación de la secuencia de comandos "sobre la marcha". De hecho, la edición de un script de larga duración tiene resultados impredecibles, insertando caracteres aleatorios, etc. ¿Por qué? Debido a que bash lee desde la posición del último byte, la edición cambia la ubicación del carácter actual que se está leyendo.

Bash es, en una palabra, muy, muy inseguro debido a esta "característica". svn y rsync cuando se usan con scripts bash son particularmente preocupantes, porque por defecto "fusionan" los resultados ... editando en su lugar. rsync tiene un modo que soluciona esto. svn y git no.

Presentamos una solución. Crear un archivo llamado "/ bin/bashx":

#!/bin/bash 
source "$1" 

Ahora use #/bin/bashx en sus guiones y siempre se ejecutan con "bashx" en lugar de fiesta!. Esto soluciona el problema: puedes sincronizar tus scripts de forma segura.

alternativa (en línea) solución propuesta/probado por @ AF7:

{ 
    # your script 
} 
exit $? 

Las llaves protegen contra las modificaciones, y la salida protege contra APPENDs. Por supuesto, todos estaríamos mucho mejor si bash tuviera una opción, como '-w' (archivo completo), o algo que hiciera esto.

+1

Por cierto; aquí hay una ventaja para contrarrestar el menos y porque me gusta su respuesta editada. –

+0

No puedo recomendar esto. En esta solución, los parámetros posicionales se cambian por uno. Recuerde también que no puede asignar un valor a $ 0. Significa que si simplemente cambia "/ bin/bash" a "/ bin/bashx", muchos scripts fallan. –

+0

¡Por favor dígame que tal opción ya se ha implementado! – AF7

Cuestiones relacionadas