Reencaminha a função e variáveis para o sudo su - user EOF

9

Eu declarei funções e variáveis no bash / ksh e preciso encaminhá-las para sudo su - {user} << EOF :

#!/bin/bash

log_f() {
echo "LOG line: $@"
}

extVAR="yourName"

sudo su - <user> << EOF
  intVAR=$(date)
  log_f ${intVAR} ${extVAR}
EOF
    
por waldauf 22.12.2014 / 15:01

3 respostas

4

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 .

    
por 23.12.2014 / 01:50
1

Isso não funciona porque a função log_f não está declarada no shell sudo su - que você inicia. Em vez disso:

extVAR="yourName"

sudo su - <user> << EOF

log_f() {
echo "LOG line: $@"
}

  intVAR=$(date)
  log_f ${intVAR} ${extVAR}
EOF

Você precisa obter a função definida no subnível raiz. Isso pode fazer isso, mas ... eu não sei o que a maioria das coisas faz. Pelo menos - contanto que nem sudo nem su precise de stdin para ler uma senha - isso deve receber log_f() declarado.

Eu acredito que você queira expandir esses valores para a entrada do shell de root, a propósito. Se você não pretende fazer isso, então você deve citar EOF e as próprias vars.

    
por 23.12.2014 / 00:16
1

No meu caso, precisei passar uma matriz e tive alguns problemas, mas tive sucesso depois de um tempo, fazendo eco dos valores da matriz para uma env -key e envolvendo o código pretendido em bash -c '<intended code>' e, basicamente, recriando o array, por exemplo: INNER_KEY=($<env_key>) .

Por exemplo:

#!/usr/bin/env bash
PLUGINS=(foo bar baz)
sudo -u <some-user> -i env PLUGINS="'echo ${PLUGINS[@]}'" sh <<'EOF'
  bash -c '
    FOO=($PLUGINS);
    echo values: \[${FOO[@]}\];

    for pl in ${FOO[@]};
      do echo value: $pl;
    done;
  '
EOF

O problema é que eu não consegui fazer algo parecido com o seguinte (não usando bash -c '...' ):

FOO=($PLUGINS);
for pl in ${FOO[@]};
...
    
por 31.12.2015 / 11:20