Qual é a diferença entre executar um comando diretamente e com 'bash -c'?

5

Para um comando (interno ou externo), qual é a diferença de     executando-o diretamente em um processo de shell bash e com bash -c em     o bash shell? Quais são suas vantagens e desvantagens     comparando um com o outro?

For example, in a bash shell, run 'date' directly, and run 'bash -c
date'. Also consider a builtin command instead of an external one.
    
por Tim 15.04.2016 / 01:12

4 respostas

9

  1. A opção -c permite que os programas executem comandos. É muito mais fácil de bifurcar e fazer

    execl("/bin/sh", "sh", "-c", "date | od -cb  &&  ps > ps.out", NULL);
    

    do que é para garfo, criar um cachimbo, garfo novamente, chame execl em cada criança, chame wait , verifique o status de saída, garfo novamente, chame close(1) , abra o arquivo, Certifique-se de que ele esteja aberto no descritor de arquivo1 e faça outro execl . Acredito que esta foi a razão pela qual a opção foi criada em primeiro lugar.

    A função de biblioteca system() executa um comando pelo método acima.

  2. Ele fornece uma maneira de obter um comando arbitrariamente complexo e fazer com que pareça um comando simples. Isso é útil em programas que executam um comando especificado pelo usuário, como find … -exec ou xargs . Mas você já sabia disso; foi parte da resposta à sua pergunta, Como especificar um comando composto como um argumento para outro comando?
  3. Pode ser útil se você estiver executando um shell interativo diferente de bash. Por outro lado, se você está executando o bash, você pode usar esta sintaxe

    $ ash  -c "command"
                 ︙
     
    $ csh  -c "command"
                 ︙
     
    $ dash -c "command"
                 ︙
     
    $ zsh  -c "command"
                 ︙

    para executar um comando em outro shell como todos esses shells também reconhecem a opção -c . Claro que você poderia alcançar o mesmo resultado com

    $ ash
    ash$ command
            ︙
    ash$ exit
     
    $ csh
    csh$ command
            ︙
    csh$ exit
     
    $ dash
    dash$ command
            ︙
    dash$ exit
     
    $ zsh
    zsh$ command
            ︙
    zsh$ exit

    Eu usei ash$  , etc., para ilustrar os prompts dos diferentes shells; você provavelmente não conseguiria isso.

  4. Pode ser útil se você quiser executar um comando em um shell bash "fresco"; por exemplo,

    $ ls -lA
    total 0
    -rw-r--r-- 1 gman gman   0 Apr 14 20:16 .file1
    -rw-r--r-- 1 gman gman   0 Apr 14 20:16 file2
    
    $ echo *
    file2
    
    $ shopt -s dotglob
    
    $ echo *
    .file1 file2
    
    $ bash -c "echo *"
    file2
    

    ou

    $ type shift
    shift is a shell builtin
    
    $ alias shift=date
    
    $ type shift
    shift is aliased to ‘date’
    
    $ bash -c "type shift"
    shift is a shell builtin
    
  5. O que precede é uma simplificação excessiva enganosa. Quando o bash é executado com -c , ele é considerado um shell não interativo , e não lê ~/.bashrc , a menos que seja -i especificado. Então,

    $ type cp
    cp is aliased to ‘cp -i’          # Defined in  ~/.bashrc
     
    $ cp .file1 file2
    cp: overwrite ‘file2’? n
     
    $ bash -c "cp .file1 file2"
                                      # Existing file is overwritten without confirmation!
    $ bash -c -i "cp .file1 file2"
    cp: overwrite ‘file2’? n

    Você pode usar -ci , -i -c ou -ic em vez de -c -i .

    Isso provavelmente se aplica até certo ponto aos outros shells mencionado no parágrafo 3, a forma longa (ou seja, a segunda forma, que é exatamente a mesma quantidade de digitação) pode ser mais seguro, especialmente se você tiver arquivos de inicialização / configuração configuração para essas conchas.

  6. Como Curinga explicado , já que você está executando uma nova árvore de processos (um novo processo shell e, potencialmente, seu (s) processo (s) filho (s)), mudanças no ambiente feitas no subshell não pode afetar o shell pai (diretório atual, valores de variáveis de ambiente, definições de funções, etc.) Portanto, é difícil imaginar um comando interno do shell isso seria útil quando executado por sh -c . fg , bg e jobs não podem afetar ou acessar trabalhos em segundo plano iniciado pelo shell pai, nem pode wait esperar por eles. sh -c "exec some_program" é essencialmente equivalente para apenas executar some_program da maneira normal, diretamente do shell interativo. sh -c exit é uma grande perda de tempo. ulimit e umask poderiam alterar as configurações do sistema para o processo filho e, em seguida, sair sem exercê-los.

    Apenas o único comando interno que seria funcional em um contexto sh -c é kill . Claro, os comandos que só produzem saída ( echo , printf , pwd e type ) não são afetados, e, se você escrever um arquivo, isso persistirá.

  7. Claro que você pode usar um builtin em conjunto com um comando externo; por exemplo.,
    sh -c "cd some_directory; some_program"
    mas você pode conseguir essencialmente o mesmo efeito com um subshell normal:
    (cd some_directory; some_program)
    que é mais eficiente. O mesmo (ambas as partes) pode ser dito para algo como
    sh -c "umask 77; some_program"
    ou ulimit (ou shopt ). E desde que você pode colocar um comando arbitrariamente complexo depois de -c - até a complexidade de um script de shell completo - Você pode ter a oportunidade de usar qualquer um dos repertórios de builtins; por exemplo, source , read , export , times , set e unset , etc.
por 15.04.2016 / 04:41
4

A execução de bash -c "my command here" vs. apenas a execução de my command here é basicamente diferente, já que o primeiro inicia uma sub-shell e o segundo executa os comandos no shell atual.

No que diz respeito a comandos incorporados versus comandos externos, ele não se relaciona realmente - qualquer coisa que você pode executar no shell atual, você pode executar em um subshell.

Existem várias diferenças nos efeitos, no entanto:

  • Alterações no ambiente feitas no subshell não podem afetar o shell pai (diretório atual, valores de variáveis de ambiente, definições de funções, etc.)
  • Variáveis definidas no shell pai que não foram exportadas estarão indisponíveis no subshell.

Isso está longe de ser uma lista exaustiva de diferenças, mas contém o ponto principal: você está executando um processo diferente com bash -c ; não é o mesmo processo que o seu shell original.

Há também um impacto no desempenho causado pela geração de um subshell; isso é mais relevante se o seu script for executado com frequência ou se o seu comando estiver dentro de um loop de algum tipo.

    
por 15.04.2016 / 02:00
2

A opção -c basicamente executa um script mini-shell fornecido como um argumento CLI em vez de um arquivo.

$ bash -c the_script the_scriptname 1 2 3 

é virtualmente equivalente a:

$ echo the_script > the_scriptname
$ bash the_scriptname 1 2 3
$ rm the_scriptname

Como você pode ver em:

$ bash -c 'printf " ->%s\n" $0 "$@"; echo $-;' scriptname 1 2 3
   ->scriptname
   ->1
   ->2
   ->3
  hBc

(em inglês:      $ 0 == scriptname; $ @ == (1 2 3);      e o bash irá:       h comandos de cinzas; executar a expansão de corrida B e ela foi executada com o -c flag)

e:

 $ echo 'printf " ->%s\n" $0 "$@"; echo $-;' > scriptname
 $ bash scriptname 1 2 3 
 ->scriptname
 ->1
 ->2
 ->3
 hB
    
por 15.04.2016 / 01:42
-1

-c string

If the -c option is present, then commands are read from string. If there are arguments after the string, they are assigned to the positional parameters, starting with $0.

Isso resolverá suas dúvidas, eu acho

    
por 15.04.2016 / 01:21

Tags