Qual é a diferença entre “source x”, “. x ”e“ ./x ”no Bash?

10

Eu tenho uma fonte de bash run.sh da seguinte forma,

#!/bin/bash
if [ $# -ne 1 ]; then
    exit
fi
...

quando eu o executo de duas maneiras, existem comportamentos diferentes. A primeira maneira é,

source run.sh

Fechará o terminal após a execução. A segunda maneira é,

./run.sh

isso simplesmente terminará a execução do script e permanecerá no terminal. Estou perguntando se existe um comando para sair de um script bash para source run.sh e ./run.sh execution. Eu tentei return também, o que não funciona bem em ./run.sh execução.

Mais geralmente, estou interessado em saber por que isso está acontecendo e qual é a diferença entre usar "source" e "." para execução de scripts?

    
por Richard 26.02.2012 / 18:11

3 respostas

16

Antes de responder, acho que alguns esclarecimentos são necessários. Vamos analisar as três linhas seguintes:

source run.sh
. run.sh
./run.sh

As duas primeiras linhas são exatamente idênticas: . é, na verdade, um alias para source . O que source faz é executar o script de shell no contexto atual, portanto, uma chamada para exit irá encerrar o shell.

A terceira linha (que é aquela que confunde você) não tem nada a ver com as outras linhas. ./run.sh é apenas um caminho e é o mesmo que (por exemplo) /home/user/run.sh ou /usr/bin/something . Lembre-se sempre de que os comandos no shell estão separados por um espaço. Então, neste caso, o comando não é . , mas é ./run.sh : isso significa que um sub-shell será executado e que o exit terá efeito apenas para o sub-shell.

    
por Andrea Corbellini 26.02.2012 / 18:39
4

Três maneiras:

Você pode colocar o script em uma função e usar apenas o retorno.

#!/usr/bin/env bash
main() {
    ...
    return 1
    ...
}
main "$@"

Você pode testar se o script está sendo originado por um shell interativo.

if [[ $- = *i* ]]; then
    return 1
else
    exit 1
fi

Você pode tentar retornar e, se falhar, saia.

return 1 2>/dev/null || exit 1
    
por geirha 26.02.2012 / 20:00
1

Pense no comando 'source' como na instrução 'include'. Ele pega o conteúdo do argumento e o executa como se fosse executado diretamente. Nesse caso, seu comando é 'source' com um argumento 'run.sh' e run.sh é executado exatamente como se você tivesse digitado o conteúdo do run.sh em sua linha de comando.

Quando você executa './run.sh', './run.sh' é o seu comando e não possui argumentos. Como este arquivo é texto puro e não binário, seu shell procura por um interpretador no shebang ('#!' Na primeira linha) e encontra '/ bin / bash'. Portanto, seu shell inicia uma nova instância do bash e o conteúdo do run.sh é executado dentro dessa nova instância.

Na primeira instância, quando o bash alcança o comando 'exit', ele é executado exatamente como se você tivesse digitado na linha de comando. Nas segundas instâncias ele é executado no processo bash que seu shell iniciou, assim somente esta instância do bash recebe um comando 'exit'.

Quando você digita uma linha no bash, qualquer coisa antes do primeiro espaço é tratada como um comando e qualquer coisa que se segue é tratada como argumentos. O comando '.' é um alias de 'fonte'. Quando você corre '. run.sh 'o'. ' é um comando por si só, pois é separado de seus argumentos por um espaço. Quando você executa './run.sh', seu comando é './run.sh' e '.' faz parte do caminho relativo para run.sh com o '.' representando sua pasta atual.

    
por smokes2345 07.04.2015 / 19:18

Tags