Como executo um comando 'sudo' dentro de um script?

84

Para fazer um patch manualmente, devo digitar este comando

sudo ./playback_delete_data_patch.sh 09_delete_old_data_p.sql  

Há um espaço logo antes do 09:

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

Como posso executar isso dentro de um script?

Existem também vários outros comandos, mas este está causando problemas.

user251948
fonte
2
Basta colocá-lo no script, qual é o problema?
Lie Ryan
6
@LieRyan - a sudo senha - o script não poderá ser executado completamente se alguém não estiver lá para inseri-lo.
Wilf
Meu sistema apenas os executa bem sem avisar. Ubuntu 16.04 em outubro de 2017. Você alterou sua sudoersconfiguração. Nada demais. Só precisa de conserto.
SDsolar 11/11
11
@SDsolar Seu sistema é o que está com problemas; é uma pequena vulnerabilidade de segurança não solicitar a senha (torna os usuários mais vulneráveis ​​a alguns tipos de ataques de engenharia social).
Wizzwizz4

Respostas:

107

Raramente é uma boa ideia ter sudoscripts internos. Em vez disso, remova o sudodo script e execute o próprio script com sudo:

sudo myscript.sh

Dessa forma, todos os comandos no script serão executados com privilégios de root e você só precisará fornecer a senha uma vez ao iniciar o script. Se você precisar que um comando específico dentro do script seja executado sem sudoprivilégios, poderá executá-lo como um usuário comum com (obrigado Lie Ryan ):

sudo -u username command 

O espaço é irrelevante, não deve afetar nada, sempre há um espaço entre um comando e seus argumentos.

terdon
fonte
30
pode haver comandos no script que não precisam de privilégios de root, você pode soltar o privilégio raiz temporariamente para os comandos usando sudo -u nome de usuário
Deite Ryan
48
Muitos scripts que escrevo fazem muita interação do usuário e / ou verificação de erros. Então, um comando no final - algo como rsync - precisa ser executado como root. Por que eu gostaria que a coisa toda funcionasse elevada e me deixasse aberta a muitas linhas de código que poderiam conter erros ou vulnerabilidades graves com acesso root - especialmente durante a depuração - quando apenas um ou alguns comandos exigem esse acesso?
Joe
2
@ Joe justo o suficiente. Mudou a "nunca uma boa idéia" para "raramente".
terdon
10
@ Joe tem um ponto muito bom aqui. Além disso, quando se diz , não faça isso , seria bom saber exatamente por que isso, ou pelo menos, em que contexto eu não deveria fazer isso, e por que
arainone
10
@terdon Você não está ouvindo. Eu sei que se você executar o script como root, ele nunca solicitará o sudo. Estou comparando isso com a não execução do script como root e a colocação de sudochamadas explícitas no script, porque elevar todo o script para root pode ser uma péssima idéia se houver apenas algumas ações estreitas que precisam de root. Nesse contexto, respondi especificamente ao seu comentário: "Em grande parte porque isso significa que você não pode executar o script automaticamente, pois precisará digitar a senha sempre que for solicitado".
BeeOnRope
41

Você pode modificar o sudoersarquivo.

Corra sudo visudo.

Adicione uma entrada para o seu nome de usuário e o script que você deseja executar sem que seja solicitada uma senha.

username ALL=(ALL) NOPASSWD: /path/to/script
Klaus-Dieter Warzecha
fonte
2
Não funcionou para mim, mas obrigado, bom saber que isso existe. Talvez eu tenha entendido errado a sintaxe.
31720 Chris K
5
Não se sabe se alguém o mencionou, mas você deve encerrar todas as sessões de login desse usuário depois de editar o sudoersarquivo.
fuga-llc
11
Apenas para esclarecer aqui, não é o script que contém a linha "sudo ./playback_delete_data_patch.sh 09_delete_old_data_p.sql" que deve ser especificada no arquivo sudoers, mas o script playback_delete_data_patch.sh ou qualquer outro comando que você deseja que esse usuário e / ou seus scripts para poder executar o sudo sem especificar uma senha.
MttJocy 8/07
19

Você pode tentar algo como:

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

Essa não é a coisa mais segura a ser feita, pois você está escrevendo uma senha do sudoer em texto sem formatação. Para torná-lo um pouco mais seguro, você pode criar uma variável e ler a senha do sudo na variável e, em seguida, executar o comando como:

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

Além disso, se você não se importa de todos os seus comandos serem executados como root, você pode simplesmente executar seu script usando sudo, como sugerido anteriormente.

sudo ./myscript
Jibbers
fonte
Lendo a senha na variável com segurança:read -s PASSWORD
Tobias Uhmann 30/04
10

Essa resposta é semelhante à resposta de Terdon . Eu também sugeriria a execução do script principal sudopara que o script possa ser executado sem precisar solicitar a senha do usuário durante sua execução.

No entanto, caso você queira descartar privilégios de root em alguns dos comandos e executá-los como o usuário real com quem o comando foi chamado sudo, você pode verificar se a $SUDO_USERvariável está configurada para descobrir o usuário original.

Este é um exemplo de script de como você pode conseguir isso:

#!/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
fonte
4

Na verdade, existe uma maneira muito mais simples de fazer isso. Para portabilidade, esta é minha implementação, mas fique à vontade para manipulá-la para atender às suas necessidades.

Digite sua senha do sudo como parâmetro ao iniciar o script, capture-o e faça eco com cada comando que solicitará a senha do 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>

Você pode adicionar um prompt e capturar após o script ser iniciado da seguinte maneira:

echo "enter the sudo password, please"
read PW

Mas se alguém monitorar o que é executado no nó; tem acesso aos logs criados por ele; ou está apenas examinando o seu deveria aleatoriamente quando você executa um teste, o que pode comprometer a segurança.

Isso também funciona com comandos / scripts em execução que requerem um sim para continuar:

echo $PW | yes | ./install.sh

O eco é uma resposta a um prompt, para que você possa usar tudo o que for necessário, se estiver executando outros scripts que solicitam progresso, em ordem seqüencial. Certifique-se de que você sabe que essa ordem pode acontecer ou coisas ruins.

csworenx
fonte
Isso é muito mais elegante e simples, fico feliz por ter rolado todo o caminho! EDIT: aguarde, isso adicionará a senha ao meu histórico de terminal
Job
11
Como pedir nome de usuário / senha com read: ryanstutorials.net/bash-scripting-tutorial/bash-input.php Isso deve evitar esse problema
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
fonte
0

Você pode tentar adicionar o usuário que executa o script ao arquivo 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
fonte
Geralmente este é um método ruim. Se você estiver indo para adicionar regras NOPASSWD sudo, especialmente para contas que correm automação, você deve no mínimo ser restringi-los para o comando exato que é executado (e não todos)
Christopher Hunter