Apa perbedaan antara sumber ('.' Atau 'sumber') dan mengeksekusi file dalam bash?

76

Apa perbedaan antara menjalankan skrip seperti ini:

./test.sh

dan menjalankan skrip seperti ini:

. test.sh?

Saya mencoba skrip dua baris sederhana untuk melihat apakah saya dapat menemukan apakah ada perbedaan:

#!/bin/bash
ls

Tetapi keduanya . test.shdan ./test.shmengembalikan informasi yang sama.

Natan
sumber
Permintaan maaf jika ini merupakan duplikat - setelah diselidiki lebih lanjut, saya menemukan beberapa halaman dengan informasi yang relevan dengan mencari 'bash dot' alih-alih 'bash.'.
Natan
3
Sama seperti test.shtidak sama dengan ./test.sh(yang pertama memanggil PATHpencarian), begitu juga . test.shdan . ./test.shberbeda dengan cara yang sama (yang pertama memanggil PATHpencarian). Banyak cangkang tampaknya secara implisit termasuk .di akhir PATHketika melakukan .pencarian jalur, tetapi perilaku ini tidak standar. Oleh karena itu, lebih akurat untuk membandingkan test.shvs . test.shdan ./test.shvs . ./test.sh.
jw013

Jawaban:

83

./test.shberjalan test.shsebagai program terpisah. Mungkin terjadi skrip bash, jika file test.shdimulai dengan #!/bin/bash. Tapi itu bisa menjadi sesuatu yang lain sama sekali.

. ./test.shmengeksekusi kode file test.shdi dalam instance bash yang sedang berjalan. Ini berfungsi seolah-olah file konten test.shtelah dimasukkan secara tekstual alih-alih . ./test.shbaris. (Hampir: ada beberapa detail yang berbeda, seperti nilai $BASH_LINENO, dan perilaku returnbuiltin.)

source ./test.shidentik dengan . ./test.shdi bash (di shell lain, sourcemungkin sedikit berbeda atau tidak ada sama sekali; .untuk dimasukkan dalam standar POSIX).

Perbedaan yang paling umum terlihat antara menjalankan skrip terpisah dengan ./test.shdan termasuk skrip dengan .builtin adalah bahwa jika test.shskrip mengatur beberapa variabel lingkungan, dengan proses terpisah, hanya lingkungan proses anak diatur, sedangkan dengan penyertaan skrip, lingkungan dari proses shell tunggal diatur. Jika Anda menambahkan baris foo=bardi test.shdan echo $foodi akhir skrip panggilan, Anda akan melihat perbedaannya:

$ cat test.sh
#!/bin/sh
foo=bar
$ ./test.sh
$ echo $foo

$ . ./test.sh
$ echo $foo
bar
Gilles
sumber
17
Menambahkan echo $$skrip juga akan menunjukkan perbedaan yang cukup jelas. The $$variabel memegang PID dari shell saat ini.
1
Skenario penggunaan lain menggunakan . ./test.shpanggilan dari dalam skrip shell lain untuk menggunakan fungsi-fungsi yang dijelaskan dalam test.sh. Maksud saya, bukan hanya variabel yang dapat Anda atur, Anda juga dapat membuat fungsi baru dengan cara ini yang kemudian dapat dipanggil dari bash, atau beberapa skrip lainnya. . /usr/libexec/company/tools; custom_command "variable"
Rqomey
9

Menjalankan skrip dengan cara pertama menjalankannya sebagai proses anak. Sourcing (cara kedua), di sisi lain, menjalankan skrip seolah-olah Anda memasukkan semua perintahnya ke shell saat ini - jika skrip menetapkan variabel, itu akan tetap ditetapkan, jika skrip keluar, sesi Anda akan keluar. Lihat help .untuk dokumentasi.

choroba
sumber
3

Hal lain yang saya perhatikan adalah jika Anda memiliki alias seperti ini:

# add into .bashrc_aliases
alias ls='ls -lht'

Dengan ./test.shAnda akan mendapatkan lsoutput normal (dan PID berbeda dari shell saat ini):

auraham@pandora:~/iso$ ./test.sh 
dsl-4.4.10.iso  test.sh
3136 # PID

Dengan . test.shatau . ./test.shAnda akan mendapatkan output yang lebih detail (dan PID yang sama dari shell saat ini):

auraham@pandora:~/iso$ echo $$
2767 # shell PID

auraham@pandora:~/iso$ . test.sh 
total 50M
drwxrwxr-x  2 auraham auraham 4.0K Jul 30 15:41 .
-rwxrwxr-x  1 auraham auraham   32 Jul 30 15:41 test.sh
drwxr-xr-x 50 auraham auraham 4.0K Jul 30 15:30 ..
-rw-rw-r--  1 auraham auraham  50M Jul 28 17:24 dsl-4.4.10.iso
2767 # PID
auraham
sumber
Anda dapat memasukkan ini ke dalam .bashrc if [ -f ~/.bash_aliases ]; then . ~/.bash_aliases fi Lalu, masukkan alias Anda .bash_aliases.
auraham
Tentu saja, tetapi bukankah Anda masih harus menggunakan aliaskata kunci? (Mungkin itu hanya kesalahan pada Anda setelah - di jalur 3?)
Emanuel Berg
sepenuhnya benar, kesalahan saya. Terima kasih @EmanuelBerg
auraham
-1

Penggunaan utama bagi saya untuk source(atau .) adalah fungsi bash .

Saya memiliki skrip dengan banyak fungsi dan saya menjalankan semuanya dengan saya .bashrc. Fungsi "menjadi" perintah, yang sering saya gunakan.

Willian Paixao
sumber
Saya mencoba ketiga metode dalam .bashrc - source, posisi absolut skrip, dan nama perintah (menempatkan skrip dalam folder PATH) - dan ketiga metode tersebut berhasil.
Emanuel Berg