2010-09-10 13 views
30

¿cómo puedo ejecutar un comando de shell en el fondo desde un script bash, si el comando está en una cadena?ejecutando el comando de shell en el fondo del script

Por ejemplo:

#!/bin/bash 
cmd="nohup mycommand"; 
other_cmd="nohup othercommand"; 

"$cmd &"; 
"$othercmd &"; 

esto no funciona - ¿cómo puedo hacer esto?

+2

Véase también [BashFAQ/050] (http://mywiki.wooledge.org/BashFAQ/050). –

Respuesta

32

dejar fuera de las comillas

$cmd & 
$othercmd & 

por ejemplo:

[email protected] /tmp 
$ cat test 
#!/bin/bash 

cmd="ls -la" 

$cmd & 


[email protected] /tmp 
$ ./test 

[email protected] /tmp 
$ total 6 
drwxrwxrwt+ 1 nicholas root 0 2010-09-10 20:44 . 
drwxr-xr-x+ 1 nicholas root 4096 2010-09-10 14:40 .. 
-rwxrwxrwx 1 nicholas None 35 2010-09-10 20:44 test 
-rwxr-xr-x 1 nicholas None 41 2010-09-10 20:43 test~ 
+2

gracias. también es necesario dejar el punto y coma por lo que puedo decir. – user248237dfsf

+0

También asegúrese de que ** no ** ponga citas alrededor de '$ cmd'. Si lo hace, intentará ejecutar un comando llamado '" ls -la "' en lugar de 'ls' con los modificadores' -la'. – GreenRaccoon23

+0

'cmd = 'some-command" con argumentos "'; $ cmd' no es ** en absoluto ** igual que 'some-command" con argumentos "'. Fallará si tiene citas en su lista de argumentos; fallará si necesita controlar cuándo están y no están expandidos los globos; fallará si se ejecuta un código que depende de la expansión de llaves o la expansión de parámetros en el momento de la ejecución. Ver [BashFAQ # 50] (http://mywiki.wooledge.org/BashFAQ/050): * Estoy tratando de poner un comando en una variable, pero los casos complejos siempre fallan! *. –

0

Esto funciona porque el que es una variable estática. Se podría hacer algo mucho más fresco como esto:

filename="filename" 
extension="txt" 
for i in {1..20}; do 
    eval "filename${i}=${filename}${i}.${extension}" 
    touch filename${i} 
    echo "this rox" > filename${i} 
done 

Este código creará 20 archivos y dinámicamente establecer 20 variables. Por supuesto, podrías usar una matriz, pero solo te estoy mostrando la característica :). Tenga en cuenta que puede usar las variables $ filename1, $ filename2, $ filename3 ... porque se crearon con el comando de evaluación. En este caso, solo estoy creando archivos, pero podría usarlos para crear dinámicamente argumentos para los comandos y luego ejecutarlos en segundo plano.

22

edificio fuera de respuesta ngoozeff 's, si usted quiere hacer una carrera de comandos completamente en el fondo (es decir, si quieres ocultar su salida y le impide ser matado al cerrar su ventana de terminal), se puede hacer esto en su lugar:

cmd="google-chrome"; 
"${cmd}" &>/dev/null &disown; 

& (la primera) se separa el comando de stdin.
>/dev/null separa la sesión de shell de stdout y stderr.
&disown elimina el comando de la lista de trabajos del shell.

También puede usar &! en lugar de &disown; ambos son el mismo comando.

Además, al poner un comando dentro de una variable, es más adecuado utilizar eval "${cmd}" en lugar de "${cmd}":

cmd="google-chrome"; 
eval "${cmd}" &>/dev/null &disown; 

Si ejecuta este comando directamente en la Terminal, se mostrará el PID del proceso que inicia el comando. Pero dentro de un script de shell, no se mostrará la salida.

He aquí una función para ello:

#!/bin/bash 

# Run a command in the background. 
_evalBg() { 
    eval "[email protected]" &>/dev/null &disown; 
} 

cmd="google-chrome"; 
_evalBg "${cmd}"; 

http://felixmilea.com/2014/12/running-bash-commands-background-properly/

+1

@ user248237dfsf @ GreenRaccoon23 'eval" $ {cmd} "' seguramente es mucho mejor que solo '$ {cmd}'. Creo que eso es lo que querías decir con '' $ {cmd} "' fallará en casos como: 'cmd = 'ls -l''. Además, '$ {cmd}' no es la solución perfecta, ya que fallará en los casos que utilicen expansiones realizadas antes de la expansión de parámetros. Entonces, por ejemplo, para 'cmd = 'touch file {1..5}''. – PesaThe

+0

'eval" $ @ "' tiene errores, si alguien espera '" $ @ "' para asegurarse de que los argumentos se pasen por separado, utilizando 'eval' anula el punto (al concatenar todos sus argumentos en una sola cadena , y luego evaluarlo). Mejor * usar * '' $ @ "' (suponiendo que los argumentos se dividirán previamente), o 'eval '$ 1' '' (esperando exactamente un argumento formateado para el análisis). –

+0

@CharlesDuffy ¿Cuál es un ejemplo de cuando 'eval" $ @ "' tiene errores? No puedo pensar en uno. Puedo pensar en casos donde '" $ @ "' sería problemático, como las variables indirectas. 'eval '$ {1}' 'ignoraría también varios argumentos, como usted señaló. 'eval" $ @ "' manejaría ambos casos extremos. Sin embargo, estoy de acuerdo en que 'eval '$ {1}' 'debería ser suficiente porque tu código debería ser coherente en la forma en que llama a esa función. Requerir las comillas en '_evalBg" $ {cmd} "' en lugar de '_evalBg $ {cmd}' hará que el código sea más manejable a largo plazo. – GreenRaccoon23

0

por ejemplo, tiene un programa de arranque llamada plazo.Para comenzar a trabajar en segundo plano, haz la siguiente línea de comando. ./run.sh &>/dev/null &

Cuestiones relacionadas