Como faço para usar o su para executar o resto do script bash como usuário?
-
22-09-2019 - |
Pergunta
Eu escrevi um script que pega, como um argumento, uma seqüência de caracteres que é uma concatenação do nome de usuário e a um projeto.O script é suposto mudar (su) para o nome de usuário, cd para um diretório específico com base no projeto de cadeia de caracteres.
Basicamente, eu gostaria de fazer:
su $USERNAME;
cd /home/$USERNAME/$PROJECT;
svn update;
O problema é que, depois de eu fazer uma su...ele apenas aguarda lá.O que faz sentido, uma vez que o fluxo de execução passou para alternar para o usuário.Uma vez que eu sair, então o resto das coisas executar, mas ele não funciona como desejado.
Eu anexado su para o comando svn, mas a falha de comando (por exemplo,não atualização do svn no diretório desejado).
Como faço para escrever um script que permite que o usuário troque de usuário e invocar o svn (entre outras coisas)?
Solução
O truque é usar o comando "sudo" em vez de "su"
Pode ser necessário adicionar isso
username1 ALL=(username2) NOPASSWD: /path/to/svn
para o seu arquivo /etc /sudoers
e mude seu script para:
sudo -u username2 -H sh -c "cd /home/$USERNAME/$PROJECT; svn update"
Onde o nome de usuário2 é o usuário que você deseja executar o comando svn como e o nome de usuário1 é o usuário executando o script.
Se você precisar de vários usuários para executar este script, use um %groupname
em vez do nome de usuário1
Outras dicas
Muito mais simples: use sudo
Para executar uma concha e usar um heredoc para alimentá -lo comandos.
#!/usr/bin/env bash
whoami
sudo -i -u someuser bash << EOF
echo "In"
whoami
EOF
echo "Out"
whoami
(responda Originalmente no SuperUser)
Use um script como o seguinte para executar o restante ou parte do script sob outro usuário:
#!/bin/sh
id
exec sudo -u transmission /bin/sh - << eof
id
eof
Você precisa executar todos os comandos do usuário diferente como seu próprio script. Se for apenas um, ou alguns comandos, então a inline deve funcionar. Se são muitos comandos, provavelmente é melhor movê -los para seu próprio arquivo.
su -c "cd /home/$USERNAME/$PROJECT ; svn update" -m "$USERNAME"
Aqui está mais uma abordagem, que foi mais conveniente no meu caso (eu só queria soltar privilégios de raiz e fazer o restante do meu script do usuário restrito): você pode fazer o script se reiniciar do usuário correto. Vamos supor que seja executado como root inicialmente. Então vai ficar assim:
#!/bin/bash
if [ $UID -eq 0 ]; then
user=$1
dir=$2
shift 2 # if you need some other parameters
cd "$dir"
exec su "$user" "$0" -- "$@"
# nothing will be executed beyond that line,
# because exec replaces running process with the new one
fi
echo "This will be run from user $UID"
...
Usar sudo
em vez de
EDITAR: Como Douglas apontou, você não pode usar cd
dentro sudo
já que não é um externo comando. Você tem que executar os comandos em uma subshell para fazer o cd
trabalhar.
sudo -u $USERNAME -H sh -c "cd ~/$PROJECT; svn update"
sudo -u $USERNAME -H cd ~/$PROJECT
sudo -u $USERNAME svn update
Você pode ser solicitado a inserir a senha desse usuário, mas apenas uma vez.
Não é possível mudar de utilizador dentro de um shell script.Soluções alternativas usando sudo descrito em outras respostas são, provavelmente, a sua melhor aposta.
Se você é louco o suficiente para executar os scripts perl como root, você pode fazer isso com o $< $( $> $)
as variáveis que possuem real/efetiva de uid/gid, por exemplo:
#!/usr/bin/perl -w
$user = shift;
if (!$<) {
$> = getpwnam $user;
$) = getgrnam $user;
} else {
die 'must be root to change uid';
}
system('whoami');
Isso funcionou para mim
Eu divida meu "provisionamento" da minha "startup".
# Configure everything else ready to run
config.vm.provision :shell, path: "provision.sh"
config.vm.provision :shell, path: "start_env.sh", run: "always"
Então no meu start_env.sh
#!/usr/bin/env bash
echo "Starting Server Env"
#java -jar /usr/lib/node_modules/selenium-server-standalone-jar/jar/selenium-server-standalone-2.40.0.jar &
#(cd /vagrant_projects/myproj && sudo -u vagrant -H sh -c "nohup npm install 0<&- &>/dev/null &;bower install 0<&- &>/dev/null &")
cd /vagrant_projects/myproj
nohup grunt connect:server:keepalive 0<&- &>/dev/null &
nohup apimocker -c /vagrant_projects/myproj/mock_api_data/config.json 0<&- &>/dev/null &
Inspirado pela ideia de @MarSoft mas eu mudei as linhas como as seguintes:
USERNAME='desireduser'
COMMAND=$0
COMMANDARGS="$(printf " %q" "${@}")"
if [ $(whoami) != "$USERNAME" ]; then
exec sudo -E su $USERNAME -c "/usr/bin/bash -l $COMMAND $COMMANDARGS"
exit
fi
Eu tenho usado sudo
para permitir uma senha com menos de execução do script.Se você quiser digitar uma senha para o usuário, remover o sudo
.Se você não precisa as variáveis de ambiente, remover -E
de sudo.
O /usr/bin/bash -l
garante, que o profile.d
os scripts são executados por um inicializado ambiente.