¿Cómo ejecutar dos comandos en sudo?

152

¿Hay alguna forma de ejecutar dos comandos Db2 desde una línea de comandos? (Se llamarán desde un execcomando PHP ).

  1. db2 connect to ttt (tenga en cuenta que necesitamos tener la conexión en vivo para el segundo comando
  2. db2 UPDATE CONTACT SET EMAIL_ADDRESS = '[email protected]'

Intenté esto:

sudo -su db2inst1 db2 connect to ttt; db2 UPDATE CONTACT SET EMAIL_ADDRESS = '[email protected]'

El primer comando finaliza correctamente pero el segundo falla con el mensaje de error SQL1024N A database connection does not exist. SQLSTATE=08003

Tenga en cuenta que necesito ejecutar esto como usuario php. El comando sudo -u db2inst1 idcomo usuario php me da la salida correcta.

Radek
fuente
deja un comentario por qué quieres cerrar esta pregunta. Gracias.
Radek
1
El voto cerrado es para la migración a serverfault, ya que esta es una pregunta de administración de sistemas, no de programación.
bdonlan

Respuestas:

157

sudo puede ejecutar múltiples comandos a través de un shell, por ejemplo:

$ sudo -s - 'whoami; quién soy'
raíz
raíz

Su comando sería algo como:

sudo -u db2inst1 -s - "db2 se conecta a ttt; db2 ACTUALIZAR CONTACTO CONFIGURAR EMAIL_ADDRESS = '[email protected]'"

Si su versión de sudo no funciona con punto y coma con -s (aparentemente, no lo hace si se compila con ciertas opciones), puede usar

sudo - sh -c 'whoami; quién soy'

en cambio, que básicamente hace lo mismo pero te hace nombrar el shell explícitamente.

wjl
fuente
12
esto no funciona en la última fiesta de Debian estable (squeeze):sudo -s -- '/usr/bin/whoami; /usr/bin/whoami' /bin/bash: /usr/bin/whoami; /usr/bin/whoami: No such file or directory
Valor
11
@Valor que puede usar sudo -- sh -c 'whoami; whoami;como solución alternativa cuando "sudo -s" no funciona. También actualicé la respuesta.
wjl
66
+1 para la versión editada que muestra el ejemplo "- sh -c". ¡Gracias!
JD.
44
¿Puede explicar por qué necesita "-"?
Vic Seedoubleyew
77
@VicSeedoubleyew El --indica el final de los parámetros para sudo, por lo que todo lo demás es parte del comando; sin él, argumentos como -cpodrían ser interpretados como un argumento para sudo. Esto funciona para la mayoría de los programas de línea de comandos (pero no para todos). Para otro (no sudo) ejemplo, para eliminar un archivo llamado -fno puedes simplemente ejecutarlo rm -f, ¿verdad? Pero puede ejecutar rm -- -fpara eliminar el archivo llamado -f.
wjl
176

Para su comando, también puede consultar el siguiente ejemplo:

sudo sh -c 'whoami; whoami'

Jason
fuente
14
He encontrado esta una alternativa más confiable.
Nick
44

Yo suelo hacer:

sudo bash -c 'whoami; whoami'
Samer Atiani
fuente
42

Si desea manejar cotizaciones:

sudo -s -- <<EOF
id
pwd
echo "Done."
EOF
Nebojša
fuente
44
Esta es la respuesta más limpia aquí, gracias. Tal vez agregue una nota "No puede ejecutar múltiples comandos desde sudo- siempre necesita engañarlo para que ejecute un shell que puede aceptar múltiples comandos para ejecutar como parámetros"
trs
8

Una alternativa que usa evalpara evitar el uso de una subshell:

sudo -s eval 'whoami; whoami'

Nota: Las otras respuestas que usan sudo -sfallan porque las citas se pasan a bash y se ejecutan como un solo comando, por lo que deben eliminarse las comillas con eval. evalse explica mejor es esta respuesta SO

Citar dentro de los comandos también es más fácil:

$ sudo -s eval 'whoami; whoami; echo "end;"'
root
root
end;

Y si los comandos deben dejar de ejecutarse si uno falla, use dos signos en lugar de punto y coma:

$ sudo -s eval 'whoami && whoamit && echo "end;"'
root
/bin/bash: whoamit: command not found
Cas
fuente
3

La -sopción no funcionó para mí, lo -ihizo.

Aquí hay un ejemplo de cómo podría actualizar el tamaño del registro desde mi bash:

sudo -u [user] -i -- sh -c 'db2 connect to [database name];db2 update db cfg for [database name] using logsecond 20;db2 update db cfg for [database name] using logprimary 20;'
usuario2597485
fuente
1

En la terminal, escriba:

$ sudo bash

Luego escribe tantos comandos como quieras. Escriba exitcuando haya terminado.

Si necesita automatizarlo, cree un script.sharchivo y ejecútelo:

$ sudo ./script.sh
Moshe Simantov
fuente
1

En un tema ligeramente relacionado, quería hacer el mismo sudo de comandos múltiples a través de SSH, pero ninguno de los anteriores funcionó.

Por ejemplo en Ubuntu,

$ ssh host.name sudo sh -c "whoami; whoami"
[sudo] password for ubuntu:
root
ubuntu

El truco descubierto aquí es comillas dobles del comando.

$ ssh host.name sudo sh -c '"whoami; whoami"'
[sudo] password for ubuntu:
root
root

Otras opciones que también funcionan:

ssh host.name sudo sh -c "\"whoami; whoami\""
ssh host.name 'sudo sh -c "whoami; whoami"'

En principio, se necesitan comillas dobles porque creo que el shell del cliente donde se ejecuta SSH elimina el conjunto de comillas más externo. Mezcle y combine las citas con sus necesidades (por ejemplo, las variables deben pasarse). Sin embargo, YMMV con las comillas, especialmente si los comandos remotos son complejos. En ese caso, una herramienta como Ansible hará una mejor elección.

Eugene Chow
fuente
1

Si conoce la contraseña de root, puede intentar

su -c "<command1> ; <command2>"  
fragmentos
fuente
Si no conoce la contraseña de root, use sudo su -c "<command1> ; <command2>" .
Dag Høidahl
0

Las respuestas anteriores no le permitirán citar dentro de las citas. Esta solución:

sudo -su nobody umask 0000 \; mkdir -p "$targetdir"

Tanto el comando umask como el comando mkdir se ejecutan con el usuario 'nobody'.

Arberg
fuente
Puede usar comillas simples y dobles y escapar de ellas.
Radek
Ok, entonces, ¿cómo es que ahora importa lo que establezca en umask en este comando, no tiene ningún efecto?
Michael