¿Cómo ejecuto un comando 'sudo' dentro de un script?

84

Para hacer un parche manualmente, debo escribir este comando

sudo ./playback_delete_data_patch.sh 09_delete_old_data_p.sql  

Hay un espacio justo antes del 09:

sudo ./playback_delete_data_patch.sh [space] 09_delete_old_data_p.sql

¿Cómo puedo ejecutar esto dentro de un script?

También hay varios otros comandos, pero este está dando problemas.

usuario251948
fuente
2
Simplemente póngalo en el script, ¿cuál es el problema?
Mentira Ryan
66
@LieRyan - la sudo contraseña - el script no podrá ejecutarse completamente si alguien no está allí para ingresarlo.
Wilf
Mi sistema solo los ejecuta bien sin preguntar. Ubuntu 16.04 en octubre de 2017. Has estropeado tu sudoersconfiguración. No es gran cosa. Solo necesita repararse.
SDsolar
1
@SDsolar Su sistema es el que está en mal estado; Es una vulnerabilidad de seguridad menor no solicitar la contraseña (hace que los usuarios sean más vulnerables a algunos tipos de ataques de ingeniería social).
wizzwizz4

Respuestas:

107

Rara vez es una buena idea tener sudoguiones internos. En su lugar, elimine el sudoscript y ejecute el script en sí con sudo:

sudo myscript.sh

De esa forma, todos los comandos dentro del script se ejecutarán con privilegios de root y solo deberá proporcionar la contraseña una vez al iniciar el script. Si necesita que se ejecute un comando particular dentro del script sin sudoprivilegios, puede ejecutarlo como un usuario normal con (gracias Lie Ryan ):

sudo -u username command 

El espacio es irrelevante, no debería afectar a nada, siempre hay un espacio entre un comando y sus argumentos.

terdon
fuente
30
puede haber comandos en el script que no necesiten el privilegio de root, puede quitar el privilegio de root temporalmente para esos comandos usando sudo -u username
Lie Ryan
48
Muchos scripts que escribo hacen un montón de interacción del usuario y / o verificación de errores. Luego, un comando al final, algo como rsync, debe ejecutarse como root. ¿Por qué querría hacer que todo se ejecute elevado y dejarme abierto a muchas líneas de código que podrían contener serios errores o vulnerabilidades con acceso a la raíz, especialmente durante la depuración, cuando solo uno o unos pocos comandos requieren ese acceso?
Joe
2
@Joe lo suficientemente justo. Cambió la "nunca es una buena idea" a "rara vez".
terdon
10
@ Joe tiene un muy buen punto aquí. Además, cuando uno dice que no haga eso , sería bueno saber exactamente por qué es eso, o al menos, en qué contexto no debería hacer eso, y por qué
arainone
10
@terdon No estás escuchando. Sé que si ejecutas el script como root , nunca te pedirá sudo. Estoy comparando eso con no ejecutar el script como root y en su lugar poner sudollamadas explícitas en el script, porque elevar todo el script a root puede ser una idea terrible si solo hay un puñado de acciones limitadas que necesitan root. En ese contexto, respondía específicamente a su comentario: "Principalmente porque esto significa que no puede ejecutar el script automáticamente, ya que deberá ingresar la contraseña cada vez que se le solicite".
BeeOnRope
41

Posiblemente podría modificar el sudoersarchivo.

Ejecutar sudo visudo.

Agregue una entrada para su nombre de usuario y el script que desea ejecutar sin que se le solicite una contraseña.

username ALL=(ALL) NOPASSWD: /path/to/script
Klaus-Dieter Warzecha
fuente
2
No funcionó para mí, pero gracias, es bueno saber que esto existe. Tal vez me equivoqué de sintaxis.
Chris K
55
No estoy seguro de que alguien lo haya mencionado, pero debe finalizar todas las sesiones de inicio de sesión de ese usuario después de haber editado el sudoersarchivo.
escape-llc
1
Solo para aclarar aquí, no es la secuencia de comandos que contiene la línea "sudo ./playback_delete_data_patch.sh 09_delete_old_data_p.sql" que debe especificarse en el archivo sudoers, sino la secuencia de reproducción_delete_data_patch.sh o cualquier otro comando que desee ese usuario y / o su scripts para poder ejecutar a través de sudo sin especificar una contraseña.
MttJocy
19

Podrías probar algo como:

echo "PASSWORD" | sudo -S ./playback_delete_data_patch.sh 09_delete_old_data_p.sql

Esto no es lo más seguro, ya que está escribiendo una contraseña de sudoer en texto sin formato. Para hacerlo un poco más seguro, puede crear una variable y leer la contraseña de sudo en la variable y luego puede ejecutar el comando como:

echo $PASSWORD | sudo -S ./playback_delete_data_patch.sh 09_delete_old_data_p.sql

Además, si no le importa que todos sus comandos se ejecuten como root, simplemente puede ejecutar su script utilizando sudo, como se sugirió anteriormente.

sudo ./myscript
Jibbers
fuente
Lectura segura de la contraseña en la variable:read -s PASSWORD
Tobias Uhmann
10

Esta respuesta es similar a la respuesta de terdon . También sugeriría ejecutar el script principal con sudopara que el script pueda ejecutarse sin tener que pedir la contraseña del usuario durante su ejecución.

Sin embargo, en caso de que desee colocar privilegios de root en algunos de los comandos y ejecutarlos como el usuario real que invocó el comando sudo, puede verificar la $SUDO_USERvariable para averiguar el usuario original.

Este es un script de ejemplo de cómo podría lograr eso:

#!/bin/bash

# ref: https://askubuntu.com/a/30157/8698
if ! [ $(id -u) = 0 ]; then
   echo "The script need to be run as root." >&2
   exit 1
fi

if [ $SUDO_USER ]; then
    real_user=$SUDO_USER
else
    real_user=$(whoami)
fi

# Commands that you don't want running as root would be invoked
# with: sudo -u $real_user
# So they will be run as the user who invoked the sudo command
# Keep in mind if the user is using a root shell (they're logged in as root),
# then $real_user is actually root
# sudo -u $real_user non-root-command

# Commands that need to be ran with root would be invoked without sudo
# root-command
Dan
fuente
4

En realidad, hay una manera mucho más simple de hacer esto. Para la portabilidad, esta es mi implementación, pero siéntase libre de manipularla para satisfacer sus necesidades.

Ingrese su contraseña de sudo como parámetro al iniciar el script, captúrelo y repítalo con cada comando que le solicitará la contraseña de sudo.

#!/bin/bash

PW=$1
echo $PW | ./playback_delete_data_patch.sh 09_delete_old_data_p.sql  
./command_wo_sudo.sh <param>
echo $PW | ./other_command_requires_sudo.sh <param>

Puede agregar una solicitud y capturar después de que se inicia el script de la siguiente manera:

echo "enter the sudo password, please"
read PW

Pero si alguien más monitorea lo que se ejecuta en el nodo; tiene acceso a los registros creados por él; o simplemente está mirando su deber al azar cuando ejecuta una prueba, eso podría comprometer la seguridad.

Esto también funciona con comandos / scripts en ejecución que requieren un sí para continuar:

echo $PW | yes | ./install.sh

El eco responde a una solicitud, por lo que puede usar cualquier cosa que necesite, allí, si está ejecutando otras secuencias de comandos que tienen indicaciones de progreso, en orden secuencial. Sin embargo, asegúrese de conocer ese orden o pueden ocurrir cosas malas.

csworenx
fuente
Eso es mucho más elegante y simple, ¡me alegro de haberme desplazado hacia abajo! EDIT: esperar, esto añadirá la contraseña de mi historial de terminal
Trabajo
1
Cómo solicitar nombre de usuario / contraseña con read: ryanstutorials.net/bash-scripting-tutorial/bash-input.php Eso debería evitar este problema
Job
3
#!/bin/bash
# this declares that current user is a sudoer
sudo tee /etc/sudoers.d/$USER <<END
END

# write the content of your script here
sudo npm install hexo-cli -g
mkdir Untitled
sudo apt-get install python

# then to remove the sudo access from the current user
sudo /bin/rm /etc/sudoers.d/$USER
sudo -k
Sanyam Jain
fuente
0

Podría intentar agregar el usuario que ejecuta el script al archivo sudoers:

#give permissions to the file
sudo chmod 700 /etc/sudoers.d/useradm

sudo visudo /etc/sudoers.d/useradm

#add the following text, changing "user" but your desired user
user ALL=(ALL)NOPASSWD:ALL

#return the right permissions to the file
sudo chmod 440 /etc/sudoers.d/useradm
evinhas
fuente
Generalmente este es un método pobre. Si va a agregar reglas de sudo NOPASSWD, especialmente para cuentas que ejecutan automatización, como mínimo debería restringirlas al comando exacto que se ejecuta (y no a TODAS)
Christopher Hunter