AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 484362
Accepted
filbranden
filbranden
Asked: 2018-11-27 20:48:02 +0800 CST2018-11-27 20:48:02 +0800 CST 2018-11-27 20:48:02 +0800 CST

"sudo -s <command>" executa o comando em um shell, mas curingas ou metacaracteres não funcionam

  • 772

Ao usar sudo -s(abreviação da opção "--shell" ), é possível passar um comando "sudo", nesse caso ele executará o comando em um shell iniciado por "sudo" como usuário de destino.

(Da mesma forma, sudo -i, também disponível como a opção "--login" , também inicia um shell e da mesma forma aceita um comando, que se comporta da mesma maneira.)

Executar comandos no sudo por meio de um shell pode ser importante em muitos casos:

  • Ao usar curingas em um diretório ao qual o usuário atual não tem acesso, mas o root tem, o comando precisa ser executado em um shell de root para que os curingas sejam expandidos adequadamente.
  • Executando um pipeline inteiro, muitos comandos encadeados em pipes ( |).
  • Ao executar um shell embutido, como for, if, etc. Executar um pequeno "script" inline inteiro em um único sudopode ser útil.

A documentação da opção "-s" diz (ênfase minha):

Execute o shell especificado pela SHELLvariável de ambiente se estiver definido ou o shell especificado pela entrada do banco de dados de senha do usuário que está chamando. Se um comando for especificado, ele será passado para o shell para execução por meio da opção -c do shell . Se nenhum comando for especificado, um shell interativo será executado. Observe que a maioria dos shells se comporta de maneira diferente quando um comando é especificado em comparação com uma sessão interativa; consulte o manual do shell para detalhes.

Em outras palavras, ao passar sudo -sum comando, ele é passado para o shell usando a -copção, que pega uma string com um "script" e depois passa a executá-lo como um script de shell.

A documentação não vai muito além sobre como usar esta opção, ou apresentar exemplos, exceto dizer "consulte o manual do shell para detalhes". Isso implica que o comando recebido é passado diretamente para a opção do shell -c. No entanto, como se vê, esse não é o caso.

Passar um script de shell com várias palavras falha:

$ sudo -s 'ls -ld /var/empty'
/bin/bash: ls -ld /var/empty: No such file or directory

A mensagem de erro indica que está tentando executar a string inteira como um comando simples... Hmmm, ok, então talvez adicionar espaços funcione? Sim, é o caso:

$ sudo -s ls -ld /var/empty
drwxr-xr-x. 3 root root 18 Jul 12 21:48 /var/empty

Mas não é bem assim que o shell -cfunciona... Bem, vamos tentar usar alguns metacaracteres, como ~, que é um atalho para o diretório home, para ver como isso se comporta. Observe as ~necessidades a serem citadas, para evitar que o shell não sudo o expanda (nesse caso, ele expandiria para a casa do usuário não root, em vez do /rootque é esperado):

$ sudo -s ls '~'
ls: cannot access '~': No such file or directory

Ok, então isso não funciona, e a saída de erro parece implicar que a expansão não está acontecendo, pois está preservando um literal ~lá.

E os curingas? Também não funciona:

$ sudo -s ls '/root/*.cfg'
ls: cannot access '/root/*.cfg': No such file or directory

Em ambos os casos, executar o comando com $SHELL -cfunciona bem. Nesse caso, $SHELLé bash, então:

$ sudo bash -c 'ls ~'
anaconda-ks.cfg
$ sudo bash -c 'ls /root/*.cfg'
/root/anaconda-ks.cfg

Uma exceção é que as variáveis ​​parecem funcionar em sudo -s, como:

$ sudo -s echo '$HOME'
/root

Então:

  • O que está acontecendo aqui?
  • Por que curingas e metacaracteres como ~não funcionam no comando passado para sudo -sou sudo -i?
  • Dado que $SHELL -crecebe uma única string com um script, mas sudo -srecebe vários argumentos, como o script é montado a partir dos argumentos?
  • Qual é uma maneira confiável de executar comandos em um shell via sudo?
shell sudo
  • 1 1 respostas
  • 1119 Views

1 respostas

  • Voted
  1. Best Answer
    filbranden
    2018-11-27T20:48:02+08:002018-11-27T20:48:02+08:00

    TL;DR: Ao tomar um comando nas opções "--shell" ou "--login", sudoirá escapar a maioria dos caracteres (usando escapes de barra invertida), incluindo todos os metacaracteres (exceto $), incluindo também espaços.

    Isso interrompe todos os casos de uso em que você deseja usar um shell, o que torna sudo -sa maioria inadequada para executar comandos de shell que precisam ser executados como comandos de shell.

    Em vez de sudo -s, use sudo sh -c '...'or sudo bash -c '...'(ou qualquer que seja o esperado $SHELL.) Em vez de sudo -i, use sudo bash -l -c '...'em vez disso (assumindo que o shell do root é bash novamente).


    Observando a parte relevante do código-fonte sudo , há este trecho:

    /* quote potential meta characters */
    if (!isalnum((unsigned char)*src) && *src != '_' && *src != '-' && *src != '$')
        *dst++ = '\\';
    *dst++ = *src;
    

    O trecho é executado em cada caractere de cada argumento. Se o caractere não for alfanumérico, sublinhado, travessão ou cifrão, ele será escapado com uma barra invertida.

    Isso significa que curingas *, ?, [...], etc. serão escapados para \*, \?, \[...\].

    Também metacaracteres como ~, ;, |, etc. serão escapados para \~, \;, \|.

    Uma string com espaços ls /rootserá escapada para ls\ /root.

    Por alguma razão, $é uma exceção no escape, é por isso que sudo -s echo '$HOME'funciona, já que o $será mantido sem escape. (Observe que isso só funciona para variáveis, e nem mesmo para o ${HOME}formulário, caso em que as chaves serão escapadas, o que quebrará a expressão.)


    As consequências dessa citação é que a maioria dos casos que exigem a execução de um shell como root não podem realmente se beneficiar do sudo -s <command>formato:

    • Os curingas não serão expandidos, pois serão escapados e não funcionarão como curingas.
    • Os pipelines não funcionarão, pois o pipe |será escapado e também não funcionará.
    • Comandos como fore ifnormalmente precisam usar ;, que será escapado e também não funcionará. Uma nova linha seria uma alternativa, mas também não parece haver uma maneira de introduzir uma nova linha sem escape.

    Resumindo, o formulário sudo -s <command>parece funcionar apenas para casos que não envolvem curingas, pipelines, scriptlets, etc. Mas então, você normalmente não precisa de um shell para executar esses comandos! Apenas executar sudo <command>sem o -snormalmente é suficiente para esses casos.

    Não está claro qual a motivação para a implementação do sudo. Talvez para manter alguma consistência entre o manuseio de comandos ao adicionar ou remover o arquivo -s. Talvez também porque -iprecede -se, nesse caso, há uma pequena diferença em como as variáveis ​​de ambiente são definidas ...


    SOLUÇÃO ALTERNATIVA: A solução alternativa é executar o shell -cexplicitamente.

    Isso envolve saber o que $SHELLé para o usuário de destino (o que pode não corresponder ao usuário atual, portanto, usar $SHELLdiretamente nem sempre é correto).

    Por exemplo, em vez de sudo -s ls -l '/root/*.cfg', use:

    $ sudo bash -c 'ls -l /root/*.cfg'
    

    E em vez de sudo -i ls -l '~', use:

    $ sudo bash -l -c 'ls -l ~'
    

    (o argumento do bash -lcria um shell de "login", que é equivalente ao criado por sudo -i.)

    • 9

relate perguntas

  • Existe uma maneira de fazer ls mostrar arquivos ocultos apenas para determinados diretórios?

  • o que grep -v grep faz

  • Execute um único comando como outro usuário; restrições ao sudo

  • Como salvar um caminho com ~ em uma variável?

  • Permitir que o usuário execute um comando como root

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    ssh Não é possível negociar: "nenhuma cifra correspondente encontrada", está rejeitando o cbc

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    Como descarregar o módulo do kernel 'nvidia-drm'?

    • 13 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add retorna com: "Erro ao conectar ao agente: nenhum arquivo ou diretório" 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve