sudo em script não interativo

9

Eu tenho um script que executa três funções: A && B && C.

A função Bprecisa ser executada como superusuário, enquanto Ae Cnão.

Eu tenho várias soluções, mas nenhuma delas é satisfatória:

  1. sudo o script inteiro: sudo 'A && B && C'

    Parece uma má ideia executar Ae Ccomo superusuário, se não for necessário

  2. torne o script interativo: A && sudo B && C

    Talvez eu precise digitar minha senha, mas quero que meu script não seja interativo, pois cada função pode levar algum tempo e não quero que o script espere por mim. Bem, é também por isso que é um script, para que eu não precise assistir.

  3. A solução estúpida: sudo : && A && sudo -n B && C

    Primeiro, parece estúpido fazer um não-op sudoprimeiro, e também devo cruzar o dedo que A não vai demorar mais do que $sudo_timeout.

  4. Solução hipotética (gostaria que você me dissesse que existe):

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

    Isso solicitaria minha senha no início e, em seguida, usaria essas credenciais somente quando necessário.

Qual a sua opinião sobre tudo isso? Eu ficaria muito surpreso por não haver solução para esse problema, pois acho que é um problema bastante comum (e quanto a make all && sudo make install)

Antoine Pelisse
fonte
3
Você poderia fazer um script que é executado com sudo, mas no script executar o Ae Cpartes explicitamente usando su -l some_non_priviliged_user. Sem problemas de tempo limite e sem privilégios para A e C. Não acho que 4 seja possível, sudoparece um "estado global" para um usuário.
Anthon

Respostas:

7

Eu acho que a melhor coisa que você pode fazer é iniciar o script sudoe, em seguida, iniciar os processos que você deseja executar como um usuário normal explicitamente com su userou 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
terdon
fonte
9

Inclua seu script no /etc/sudoersarquivo com o NOPASSWDatributo, para que ele possa ser executado sem solicitar uma senha. Você pode vincular isso a um usuário específico (ou conjunto de usuários) ou permitir que ele seja executado sudopor qualquer pessoa em seu sistema.

Uma linha de amostra para um script chamado /usr/local/bin/bossypode ser algo como isto

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

E você usaria algo assim

A && sudo bossy && C

Para este exemplo, assumi que PATHinclui /usr/local/bin. Caso contrário, use o caminho completo para o script, ou seja,sudo /usr/local/bin/bossy

roaima
fonte
Voto positivo para a abordagem mais segura.
eyoung100
0

Você pode querer usar a !requirettyopção sudoassim como a NOPASSWDopção. Mas lembre-se de que isso reduz a segurança.

Steve Wills
fonte
1
Como o problema é definido como não querendo que o script para ser interativo, # 2, com /etc/sudoersentrada para o usuário a executar o comando Bcom NOPASSWDé a resposta certa.
Andrew
Isso é "você pode fazer X ou Y", é "você pode fazer X e Y". Somente ambos resolverão o problema. Talvez eu deva reformular minha resposta.
Steve Wills
0

Com base na minha resposta para pré-autorizar o sudo? (Para que possa ser executado posteriormente) , escreva dois 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

Execute ./ABC_script:

  • Vai correr sudo -b ./B_script. Isso solicita a senha ( imediatamente após a execução ABC_script). Assumindo que a senha correta foi inserida, ela gera B_scriptno fundo b (porque -bfoi especificada) como raiz. Isso parece ser equivalente a sudo sh -c "./B_script &".
  • B_scriptcomeça a ser executado de forma assíncrona, em paralelo com ABC_scriptB_scripttesta a existência de um arquivo chamado A_is_done e faz um loop até aparecer.
  • Em paralelo, ABC_scripté executado A. Se / quando Aterminar com êxito, o script criará um arquivo chamado A_is_done.
  • ABC_scriptdepois testa a existência de um arquivo chamado B_is_done e faz um loop até aparecer.
  • Paralelamente, B_scriptdetecta a existência A_is_donee rompe o loop. Exclui o A_is_donearquivo e é executado B. Lembre-se, B_scriptestá sendo executado como root, por isso é executado Bcomo root. Se / quando Bterminar com êxito, o script cria um arquivo chamado B_is_donee sai.
  • Paralelamente, ABC_scriptdetecta a existência B_is_donee rompe o loop. Exclui o B_is_donearquivo. Lembre-se de que foi B_scriptexecutado como root, portanto, ele B_is_donepertence ao root e você deseja usá-lo rm -fpara evitar a solicitação de confirmação. ABC_scriptdepois corre Ce sai.

Notas para aperfeiçoamento adicional:

  • ABC_scriptprovavelmente deve ser executado B_scriptpor um caminho absoluto e não ./.
  • Em vez de A_is_donee B_is_done, ABC_scriptprovavelmente deve gerar nomes de arquivos aleatórios e únicos.
  • É necessário que haja uma provisão para que o script que está aguardando rotação seja notificado se o programa que está aguardando foi concluído, mas falhou. (No momento, se Afalhar, os dois scripts entrarão em um loop de espera infinito.) Isso pode ser tão simples quanto mudar

    A  &&  > A_is_done

    para

    A; echo $? > A_is_done

    e, em seguida, modifique as esperas de rotação para ler os X_is_donearquivos e continue se ele contiver 0 e saia do contrário.

Scott
fonte
-3

Seja burro. use muitas linhas.

if A; then

    if sudo B ; then
        C
    fi
fi
Robert Jacobs
fonte
como isso resolve alguma das minhas preocupações? O problema não tem nada a ver com&&
Antoine Pelisse
&& interrompe a execução quando o primeiro comando falha. As instruções if fazem isso mais detalhadamente. Meu objetivo é fazer o seu trabalho, mesmo que não seja bonito.
Robert Jacobs
1
Isso não é nada mais do que uma versão mais detalhada da Opção 2: A && sudo B && C. Assim como Antoine explica na pergunta; isso não pede a senha até Aque termine, e ele não deseja esperar por isso ou o script espera por ele.
Scott