usando su dentro de un script de shell


12

Estoy automatizando un proceso de implementación y quiero poder simplemente llamar un archivo .sh en mi máquina, hacer que compile y cargue el .zip en el servidor y luego haga un montón de cosas en el servidor. Una de las cosas que necesito hacer requiere que sea root. Entonces, lo que quiero hacer es esto:

ssh user@172.1.1.101 <<END_SCRIPT
su - 
#password... somehow...
#stop jboss
service server_instance stop
#a bunch of stuff here
#all done!
exit
END_SCRIPT

¿Es esto posible?


+1 buena pregunta. problema comun.
gMale

Respuestas:


15

¿Has considerado un sudo sin contraseña en su lugar?


1
Este es el enfoque que he usado en el pasado. Puede limitar sudo a los comandos requeridos (iniciar / detener el servicio), limitando los privilegios que tiene el usuario a lo que necesita. Todavía se siente torpe, pero funciona.
Marque el

Esto es en realidad lo que terminé haciendo ...
cmcculloh

5

En lugar de su, use sudo con el NOPASSWD establecido en sudoers para los comandos apropiados. Deberá hacer que el conjunto de comandos permitido sea lo más limitado posible. Hacer que ejecute un script para los comandos raíz puede ser la forma más limpia y, con mucho, más fácil de asegurar si no está familiarizado con la sintaxis del archivo sudoer. Para los comandos / scripts que requieren que se cargue el entorno completo, sudo su - -c commandfunciona aunque puede ser excesivo.



3

Puede pasar un comando como argumento a SSH para ejecutar ese comando en el servidor y luego salir:

ssh user@host "command to run"

Esto también funciona para una lista de múltiples comandos:

ssh user@host "command1; command2; command3"

O alternativamente:

ssh user@host "
        command1
        command2
        command3
"

Como otros usuarios han señalado antes que yo, ejecutar suen el servidor lanzará un nuevo shell en lugar de ejecutar comandos posteriores en el script como root. Lo que debe hacer es usar uno sudoo su -c, y forzar la asignación de TTY a SSH con el -tinterruptor (requerido si necesita ingresar la contraseña de root):

ssh -t user@host 'su - -c "command"'
ssh -t user@host 'sudo command'

En resumen, una forma de lograr lo que quieres hacer sería:

#!/bin/bash
ssh -t user@172.1.1.101 "
        sudo some_command
        sudo service server_instance stop
        sudo some_other_command
"

Como sudonormalmente recuerda su nivel de autorización durante unos minutos antes de solicitar nuevamente la contraseña de root, simplemente anteponer sudotodos los comandos que necesita ejecutar como root es probablemente la forma más fácil de ejecutar comandos como root en el servidor. Agregar una NOPASSWDregla para su usuario /etc/sudoershará que el proceso sea aún más sencillo.

Espero que esto ayude :-)


Si necesita más información sobre cómo agregar esa NOPASSWDregla, consulte los ejemplos en la parte inferior de man sudoers. Además, recuerde usarlo visudocuando edite su sudoersarchivo para evitar roturas.
jabirali

No puedo hacer que el su - -c "comando" funcione. ¿Cómo proporcionaría la contraseña para su?
cmcculloh

Si elige usar en su -clugar de sudo, debe ejecutar SSH con el -tindicador; se le pedirá la contraseña de root en el servidor cuando se ejecute el comando. Proporcionar una contraseña directamente sucomo un argumento de línea de comandos es compatible ni (por lo que sé), ni recomendable - desde un simple ps -ef | grep surevela todos los argumentos que se pasan a su, incluyendo cualquier contraseña proporcionada desde la línea de comandos ...
jabirali

En cuanto a cómo invocar a su -ctravés de SSH: ssh -t user@host 'su -lc "<br /> echo this is a test <br /> echo this is another test<br /> "<br />'
jabirali

Reemplace lo <br />anterior con nuevas líneas en su secuencia de comandos. Fuera de tema: ¿Puede agregar nuevas líneas a los comentarios de ServerFault? Eso sería bastante útil al publicar fragmentos de código ...
jabirali

2

No. Incluso si obtiene la contraseña su, todavía tiene que lidiar con el hecho de que suabrirá un nuevo shell, lo que significa que no se le pasarán más comandos. Deberá escribir un script para las operaciones raíz junto con un ejecutable auxiliar que pueda invocarlo con los privilegios apropiados.


2
La mayoría de los comandos su aceptan la opción -c, que tomará como argumento los comandos que se ejecutarán. Estoy de acuerdo en que una secuencia de comandos en el servidor en sí es probablemente mejor que enviar todos los cmds a través de ssh.
Aaron Bush

1

Escribe un guión de esperar. Sé que ya ha encontrado una respuesta para esto, pero esto podría ser útil si tiene que iniciar sesión en un grupo de servidores que requieren la entrada de contraseña interactiva.

Es un lenguaje basado en TCL, por lo que puede ser un poco extraño en comparación con los viejos scripts de shell. Pero maneja la automatización del ingreso de texto y, lo adivinó, "espera" ciertos bits de salida antes de ingresar cualquier tipo de ingreso automático de contraseña o escalada de privilegios.

Aquí hay un buen enlace como guía: http://bash.cyberciti.biz/security/expect-ssh-login-script/

En caso de que el sitio se caiga:

#!/usr/bin/expect -f
# Expect script to supply root/admin password for remote ssh server
# and execute command.
# This script needs three argument to(s) connect to remote server:
# password = Password of remote UNIX server, for root user.
# ipaddr = IP Addreess of remote UNIX server, no hostname
# scriptname = Path to remote script which will execute on remote server
# For example:
#  ./sshlogin.exp password 192.168.1.11 who
# ------------------------------------------------------------------------
# Copyright (c) 2004 nixCraft project <http://cyberciti.biz/fb/>
# This script is licensed under GNU GPL version 2.0 or above
# -------------------------------------------------------------------------
# This script is part of nixCraft shell script collection (NSSC)
# Visit http://bash.cyberciti.biz/ for more information.
# ----------------------------------------------------------------------
# set Variables
set password [lrange $argv 0 0]
set ipaddr [lrange $argv 1 1]
set scriptname [lrange $argv 2 2]
set arg1 [lrange $argv 3 3]
set timeout -1
# now connect to remote UNIX box (ipaddr) with given script to execute
spawn ssh root@$ipaddr $scriptname $arg1
match_max 100000
# Look for passwod prompt
expect "*?assword:*"
# Send password aka $password
send -- "$password\r"
# send blank line (\r) to make sure we get back to gui
send -- "\r"
expect eof

1

Sé que esto es un poco tarde, pero personalmente usaría Net :: SSH :: Expect, disponible de CPAN.

http://search.cpan.org/~bnegrao/Net-SSH-Expect-1.09/lib/Net/SSH/Expect.pod


Esperar es realmente agradable en muchos de esos casos si no puede usar ssh / bash scripting regular. Sin embargo, también se vuelve realmente torpe rápidamente y te hace asumir "lo que sea que encuentres" en el extremo remoto. Si se puede cambiar el sistema de destino o influencia cómo se comporta en absoluto Recomiendo probar primero una ruta diferente. Sin embargo, es un buen punto traerlo aquí.
Theuni

0

Puede usar 'ssh example.com su -lc "$ cmd"'.

Cuando el comando contiene opciones, debe citarlo; de lo contrario, "su" podría comerlas ("su: opción no válida - 'A').

ssh -AX -tt example.com 'su -lc "tmux new-session -A"'
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.