sudo en script no interactivo


9

Tengo un script que ejecuta tres funciones: A && B && C.

La función Bdebe ejecutarse como un superusuario, mientras que Ay Cno.

Tengo varias soluciones, pero ninguna de estas es satisfactoria:

  1. sudo el guión completo: sudo 'A && B && C'

    Parece una mala idea ejecutar Ay Ccomo superusuario si no es necesario

  2. hacer el guión interactivo: A && sudo B && C

    Es posible que tenga que escribir mi contraseña, pero quiero que mi script no sea interactivo, ya que cada función puede tomar un tiempo, y no quiero que el script me espere. Bueno, esa es también la razón por la cual es un script en primer lugar, así que no tengo que verlo correr.

  3. La estúpida solución: sudo : && A && sudo -n B && C

    Primero parece estúpido ejecutar un no-op sudoprimero, y también debo cruzar el dedo para que A no vaya a tomar más que $sudo_timeout.

  4. Solución hipotética (deseo que me digas que existe):

    sudo --store-cred 'A && sudo --use-cred-from-parent-sudo B && C'

    Eso solicitaría mi contraseña al principio, y luego usaría esas credenciales solo cuando sea necesario.

¿Cuál es tu opinión sobre todo esto? Me sorprendería mucho que no haya una solución a ese problema, ya que creo que es un problema bastante común (¿qué pasa? make all && sudo make install)


3
Puede crear un script que ejecute con sudo, pero en el script ejecute explícitamente las partes Ay . Sin problemas de tiempo de espera y sin privilegios para A y C. No creo que 4 sea posible, parece un "estado global" para un usuario. Csu -l some_non_priviliged_usersudo
Anthon

Respuestas:


7

Creo que lo mejor que puede hacer es iniciar el script sudoy luego iniciar los procesos que desea ejecutar como usuario normal explícitamente con su usero sudo -u user:

#!/usr/bin/env bash

## Detect the user who launched the script
usr=$(env | grep SUDO_USER | cut -d= -f 2)

## Exit if the script was not launched by root or through sudo
if [ -z $usr ] && [ $USER = "root" ]
then
    echo "The script needs to run as root" && exit 1
fi

## Run the job(s) that don't need root
sudo -u $usr commandA

## Run the job that needs to be run as root
commandB

9

Agregue su secuencia de comandos al /etc/sudoersarchivo con el NOPASSWDatributo, para que se pueda ejecutar sin solicitar una contraseña. Puede vincular esto a un usuario específico (o conjunto de usuarios), o permitir que sudocualquier persona en su sistema lo ejecute .

Una línea de muestra para un script llamado /usr/local/bin/bossypodría verse así

ALL ALL = (root) NOPASSWD: /usr/local/bin/bossy

Y luego usarías algo como esto

A && sudo bossy && C

Para este ejemplo supuse PATHincluye /usr/local/bin. Si no es así, simplemente use la ruta completa al script, es decirsudo /usr/local/bin/bossy


Vota por el enfoque más seguro.
eyoung100

0

Es posible que desee utilizar la !requirettyopción sudo, así como la NOPASSWDopción. Pero tenga en cuenta que esto reduce la seguridad.


1
Como el problema se define como no queriendo la secuencia de comandos para ser interactivo, # 2 con /etc/sudoersentrada para el usuario para ejecutar comandos Bcon NOPASSWDes la respuesta correcta.
Andrew

Eso es "podrías hacer X o Y", era "podrías hacer X e Y". Solo ambos resolverán el problema. Quizás debería volver a redactar mi respuesta.
Steve Wills

0

¿Aprovechando mi respuesta para preautorizar sudo? (Para que pueda ejecutarse más tarde) , escriba dos scripts:

  • ABC_script:

    #!/bin/sh
    sudo -b ./B_script
    A  &&  > A_is_done
    while [ ! -f B_is_done ]
    do
            sleep 60
    done
    rm -f B_is_done
    C
  • B_script:

    #!/bin/sh
    while [ ! -f A_is_done ]
    do
            sleep 60
    done
    rm -f A_is_done
    B  &&  > B_is_done

Ejecutar ./ABC_script:

  • Correrá sudo -b ./B_script. Esto solicita la contraseña ( inmediatamente después de ejecutar ABC_script). Suponiendo que se introduzca la contraseña correcta, se genera B_scripten el b ANTECEDENTES (porque -bse especificó) como root. Esto parece ser equivalente a sudo sh -c "./B_script &".
  • B_scriptcomienza a ejecutarse de forma asincrónica, en paralelo con ABC_scriptB_scriptprueba la existencia de un archivo llamado A_is_done y realiza un bucle hasta que aparece.
  • En paralelo, ABC_scriptcorre A. Si / cuando Afinaliza con éxito, el script crea un archivo llamado A_is_done.
  • ABC_scriptluego prueba la existencia de un archivo llamado B_is_done y realiza un bucle hasta que aparece.
  • Paralelamente, B_scriptdetecta la existencia de A_is_doney sale del bucle. Elimina el A_is_donearchivo y se ejecuta B. Recuerde, B_scriptse ejecuta como root, por lo que se ejecuta Bcomo root. Si / cuando Bfinaliza con éxito, el script crea un archivo llamado B_is_doney sale.
  • Paralelamente, ABC_scriptdetecta la existencia de B_is_doney sale del bucle. Borra el B_is_donearchivo. Recuerde, se B_scriptejecutó como root, por lo que B_is_donees propiedad de root, y desea usarlo rm -fpara evitar recibir una solicitud de confirmación. ABC_scriptluego corre Cy sale.

Notas para un mayor refinamiento:

  • ABC_scriptprobablemente debería ejecutarse B_scriptpor una ruta absoluta en lugar de ./.
  • En lugar de A_is_doney B_is_done, ABC_scriptprobablemente debería generar nombres de archivo únicos y aleatorios.
  • Es necesario que haya una provisión para el script que está en espera de ser notificado si el programa que está esperando ha finalizado pero ha fallado. (En este momento, si Afalla, ambos scripts simplemente entran en un ciclo de espera infinito). Esto podría ser tan simple como cambiar

    A  &&  > A_is_done

    a

    A; echo $? > A_is_done

    y luego modificando los spin-waits para leer los X_is_donearchivos, y proceder si contiene 0 y salir de lo contrario.


-3

Se tonto Usa muchas líneas.

if A; then

    if sudo B ; then
        C
    fi
fi

¿Cómo está resolviendo eso alguna de mis preocupaciones? El problema no tiene nada que ver con&&
Antoine Pelisse

&& detiene la ejecución cuando falla el primer comando. Las declaraciones if hacen esto de manera más detallada. Mi punto es hacer tu trabajo, incluso si no es bonito.
Robert Jacobs

1
Esto no es nada más que una versión más detallada de la opción 2: A && sudo B && C. Tal como Antoine explica en la pregunta; esto no pide la contraseña hasta que Ahaya terminado, y no quiere tener que esperar eso, o que el script lo espere.
Scott
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.