“comando não encontrado” quando a função sudo'ing é de ~ / .zshrc

8

Eu tenho uma função no meu ~/.zshrc :

findPort() {
    lsof -t -i :$1
}

A invocação usual é findPort 3306 .

Eu quero executá-lo com privilégios elevados. Mas eu recebo "comando não encontrado".

➜  git                     
por Birchlabs 20.10.2016 / 14:42

3 respostas

10

sudo executa comandos diretamente, não por meio de um shell, e mesmo se ele executasse um shell para executar esse comando, seria uma nova invocação de shell e não uma que lê seu ~/.zshrc (mesmo que tenha iniciado um Como o shell interativo, ele provavelmente leu root ~/.zshrc , não seu, a menos que você tenha configurado sudo para não redefinir a variável $HOME ).

Aqui, você precisa informar sudo para iniciar um novo zsh shell e informar que zsh ler seu ~/.zshrc antes de executar essa função:

sudo zsh -c '. $0; "$@"' ~/.zshrc findPort 3306

Ou:

sudo zsh -c '. $0; findPort 3306' ~/.zshrc

Ou para compartilhar suas funções zsh atuais com o novo zsh chamado por sudo :

sudo zsh -c "$(functions); findPort 3306"

Embora você possa ter um erro lista de arges por muito tempo se você tiver muitas funções definidas (como ao usar o sistema de conclusão). Então você pode querer limitá-lo para a função findPort (e todas as outras funções nas quais ele se baseia):

sudo zsh -c "$(functions findPort); findPort 3306"

Você também pode fazer:

sudo zsh -c "(){$functions[findPort]} 3306"

Para incorporar o código da função findPort em uma função anônima para a qual você passa o argumento 3306. Ou até mesmo:

sudo zsh -c "$functions[findPort]" findPort 3306

(o script in-line passado para -c é o corpo da função).

Você pode usar uma função auxiliar como:

zsudo() sudo zsh -c "$functions[$1]" "$@"

Não use:

sdo() { sudo zsh -c "(){$functions[$1]} ${@:2}" }

Como os argumentos de sdo passariam por outro nível de análise de shell. Comparar:

$ e() echo "$@"
$ sdo e 'tname;uname'
tname
Linux
$ zsudo e 'tname;uname'
tname;uname
    
por 20.10.2016 / 14:58
2

Eu consegui produzir um shorthand reutilizável para uma das soluções descritas em de Stéphane Chazelas responder . [Edit: Stéphane iterou no atalho original que propus; o código descrito aqui é uma versão mais recente, de sua criação]

Coloque isso no seu ~/.zshrc :

sdo() sudo zsh -c "$functions[$1]" "$@"

Agora você pode usar sdo como " sudo apenas para funções definidas pelo usuário".

Para confirmar que sdo funciona: você pode testá-lo em uma função definida pelo usuário que imprima seu nome de usuário.

➜ birch@server ~/                                     
por 20.10.2016 / 18:18
2

Uma solução muito simples para mim foi invocar um shell interativo usando sudo -s , que parece funcionar na minha versão do zsh (5.2). Isso me fornece as funções do meu ~/.zshrc .

A partir da página de manual do sudo, o que não indica realmente este comportamento:

-s, --shell
Run the shell specified by the SHELL environment variable if it is set or the shell specified by the invoking user's password database entry. If a command is specified, it is passed to the shell for execution via the shell's -c option. If no command is specified, an interactive shell is executed.

Não sei qual é o seu caso de uso, mas suspeito que você esteja procurando uma solução interativa.

    
por 23.10.2016 / 12:46

Tags