Eu tenho um script que faz várias coisas diferentes, a maioria das quais não requer privilégios especiais. No entanto, uma seção específica, que eu conti em uma função, precisa de privilégios de root.
Não desejo exigir que o script inteiro seja executado como root e quero poder chamar essa função, com privilégios de root, de dentro do script. Solicitar uma senha, se necessário, não é um problema, pois, na maioria das vezes, é interativo. No entanto, quando tento usar sudo functionx
, recebo:
sudo: functionx: command not found
Como eu esperava, export
não fez diferença. Eu gostaria de poder executar a função diretamente no script, em vez de quebrá-la e executá-la como um script separado por vários motivos.
Existe alguma maneira de tornar minha função "visível" para o sudo sem extraí-la, encontrar o diretório apropriado e executá-la como um script independente?
A função tem aproximadamente uma página e contém várias seqüências de caracteres, algumas com aspas duplas e outras com aspas simples. Também depende de uma função de menu definida em outra parte do script principal.
Eu só esperaria que alguém com sudo QUALQUER capaz de executar a função, pois uma das coisas que faz é alterar as senhas.
declare
também elas.Respostas:
Admito que não há uma maneira simples e intuitiva de fazer isso, e isso é um pouco hackey. Mas você pode fazer assim:
Ou, mais simplesmente:
Funciona para mim:
Basicamente,
declare -f
retornará o conteúdo da função, que você passará para abash -c
linha.Se você deseja exportar todas as funções da instância externa do bash, altere
FUNC=$(declare -f hello)
paraFUNC=$(declare -f)
.Editar
Para abordar os comentários sobre a citação, consulte este exemplo:
fonte
echo "Hello!"
é efetivamente o mesmo queecho Hello!
(ou seja, aspas duplas não fazem diferença para esse comando de eco específico). Em muitas / na maioria das outras circunstâncias, as aspas duplas na função provavelmente quebrarão obash -c
comando.bash -xc
e não apenasbash -c
) e parecebash
ser inteligente o suficiente para re-citar as coisas nessa situação, mesmo na medida de substituir aspas duplas por aspas simples e mudar'
para,'\''
se necessário. Eu tenho certeza que haverá alguns casos que ele não pode resolver, mas definitivamente funciona para casos pelo menos simples e moderadamente complexos - por exemplo, tryfunction hello() { filename="this is a 'filename' with single quotes and spaces" ; echo "$filename" ; } ; FUNC=$(declare -f hello) ; bash -xc "$FUNC ; hello"
declare -f
imprime a definição da função de uma maneira que pode ser analisada novamente pelo bash, assimbash -c "$(declare -f)"
como funciona corretamente (assumindo que o shell externo também seja do bash). O exemplo que você postou mostra-lo funcionando corretamente - onde as citações foram alteradas é no rastreamento , porque festança imprime traços em sintaxe shell, por exemplo, tentarbash -xc 'echo "hello world"'
sudo yourFunction
sendo encontrado (caso contrário, você recebe um erro de segmentação da recursão)O "problema" é que
sudo
limpa o ambiente (exceto algumas variáveis permitidas) e define algumas variáveis com valores seguros predefinidos para proteger contra riscos de segurança. em outras palavras, isso não é realmente um problema. É uma característica.Por exemplo, se você definiu
PATH="/path/to/myevildirectory:$PATH"
esudo
não definiu PATH para um valor predefinido, qualquer script que não especificasse o nome completo do caminho para TODOS os comandos executados (ou seja, a maioria dos scripts) procuraria/path/to/myevildirectory
antes de qualquer outro diretório. Coloque comandos comols
ougrep
ou outras ferramentas comuns lá e você poderá facilmente fazer o que quiser no sistema.A maneira mais fácil / melhor é reescrever a função como um script e salvá-la em algum lugar no caminho (ou especificar o caminho completo para o script na
sudo
linha de comando - o que você precisará fazer de qualquer maneira, a menos quesudo
esteja configurado para permitir que você para executar QUALQUER comando como root) e torná-lo executável comchmod +x /path/to/scriptname.sh
Reescrever uma função shell como um script é tão simples como apenas salvar os comandos dentro da definição da função para um arquivo (sem a
function ...
,{
e}
linhas).fonte
sudo -E
Evita também limpar o meio ambiente.Eu escrevi minha própria
Sudo
função bash para fazer isso, funciona para chamar funções e aliases:fonte
Você pode combinar funções e aliases
Exemplo:
então
sudo hello
funcionafonte
Aqui está uma variação da resposta de Will . Envolve um
cat
processo adicional , mas oferece o conforto do heredoc. Em poucas palavras, é assim:Se você quiser mais informações, tente o seguinte:
A saída é:
Aqui temos a
menu
função correspondente à da pergunta, que é "definida em outra parte do script principal". Se "em outro lugar" significa que sua definição já foi lida nesta fase quando a função exigentesudo
está sendo executada, a situação é análoga. Mas pode não ter sido lido ainda. Pode haver outra função que ainda acionará sua definição. Nesse casodeclare -f menu
, deve ser substituído por algo mais sofisticado ou o script inteiro corrigido de forma que amenu
função já esteja declarada.fonte
menu
função teria sido declarada antes deste ponto, comof
é chamada em um menu.Supondo que seu script seja (a) independente ou (b) possa obter seus componentes com base em sua localização (em vez de lembrar onde está o diretório inicial), você pode fazer algo assim:
$0
nome do caminho para o script, usando osudo
comando, e passe uma opção que o script verificará para chamar a atualização da senha. Contanto que você encontre o script no caminho (em vez de apenas executar./myscript
), deverá obter um nome de caminho absoluto$0
.sudo
executa o script, ele tem acesso às funções necessárias no script.uid
e perceberia que ele foi executado como usuário raiz e, como ele possui a opção definida para solicitar a atualização da senha, vá e faça naquela.Os scripts podem se repetir por vários motivos: a alteração de privilégios é um deles.
fonte