sudo su - , que é uma maneira complicada de escrever sudo -i , constrói um ambiente primitivo. Esse é o ponto de um shell de login. Mesmo um sudo simples remove a maioria das variáveis do ambiente. Além disso sudo é um comando externo; não há como elevar privilégios no próprio shell script, apenas para executar um programa externo ( sudo ) com privilégios extras, e isso significa que quaisquer variáveis de shell (ou seja, variáveis não exportadas) e funções definidas no shell pai não estar disponível no shell filho.
Você pode transmitir variáveis de ambiente por meio da não invocação de um shell de login ( sudo bash em vez de sudo su - ou sudo -i ) e da configuração do sudo para permitir que essas variáveis passem (com Defaults !env_reset ou Defaults env_keep=… no sudoers Arquivo). Isso não ajudará em funções (embora o bash tenha um recurso de exportação de função, o sudo o bloqueia).
A maneira normal de obter suas funções no shell filho seria defini-las lá. Tome cuidado com as citações: se você usar <<EOF para o documento here, o conteúdo do documento here é expandido primeiro pelo shell pai e o resultado dessa expansão se torna o script que o shell filho vê. Isto é, se você escreve
sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF
exibe o nome do usuário original, não o usuário de destino. Para evitar essa primeira fase de expansão, cite o marcador de documento aqui após o operador << :
sudo -u "$target_user" -i <<'EOF'
echo "$(whoami)"
EOF
Então, se você não precisa passar dados do shell pai para o shell filho, você pode usar um documento citado aqui:
#!/bin/bash
sudo -u "$target_user" -i <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}"
EOF
Embora você possa usar um marcador de documento não mencionado aqui para passar dados do shell pai para o shell filho, isso só funcionará se os dados não contiverem nenhum caractere especial. Isso porque em um script como
sudo -u "$target_user" -i <<EOF
echo "$(whoami)"
EOF
a saída de whoami se torna um pouco de código shell, não uma string. Por exemplo, se o comando whoami retornasse "; rm -rf /; "true , o shell filho executaria o comando echo ""; rm -rf /; "true" .
Se você precisar passar dados do shell pai, uma maneira simples é passá-lo como argumentos. Invoque o shell filho explicitamente e passe-o aos parâmetros posicionais:
#!/bin/bash
extVAR="yourName"
sudo -u "$target_user" -i sh _ "$extVAR" <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}" "${1}"
EOF
Se você tiver várias variáveis para passar, será mais legível passá-las pelo nome. Chame env explicitamente para definir variáveis de ambiente para o shell filho.
#!/bin/bash
extVAR="yourName"
sudo -u "$target_user" -i env extVAR="$extVAR" sh <<'EOF'
log_f() {
echo "LOG line: $@"
}
intVAR=$(date)
log_f "${intVAR}" "${1}"
EOF
Se você espera que /etc/profile e% de% do usuário alvo sejam lidos, será preciso lê-los explicitamente ou chamar ~/.profile em vez de bash --login .