Perbedaan utamanya adalah mereka dieksekusi dalam proses yang berbeda.
Jadi jika Anda source
file foo
yang melakukan cd
, shell sumber (misalnya shell interaktif Anda di terminal) terpengaruh (dan direktori saat ini akan berubah)
Jika Anda menjalankan sh foo
cd
tidak memengaruhi shell sumber, hanya sh
yang baru dibuat proses menjalankan foo
Baca Panduan Pembuatan Skrip Bash Tingkat Lanjut.
Seperti yang telah disebutkan orang lain, saat Anda menjalankan sh test.sh
, setiap perubahan yang test.sh
membuat ke lingkungan shell Anda tidak akan bertahan setelah proses berakhir.
Namun, perhatikan juga bahwa setiap elemen lingkungan Anda yang tidak diekspor (misalnya, variabel, alias, dan fungsi shell) tidak akan tersedia untuk kode di test.sh
ketika dijalankan sebagai subproses (yaitu dengan sh test.sh
).
Misalnya:
$ cat > test.sh
echo $foo
$ foo=bar
$ sh test.sh
$ . test.sh
bar
Contoh 2:
[email protected]:~$ cat test.sh
#!/bin/sh
cd /etc
[email protected]:~$ sh test.sh
[email protected]:~$ pwd
/home/savoury
[email protected]:~$ source test.sh
[email protected]:/etc$ pwd
/etc
[email protected]:/etc$
Saat Anda memanggil source
atau .
(yang satu adalah alias dari yang lain. source
cmd bukan POSIX - semacam bashism ), Anda memuat dan menjalankan skrip shell ke dalam arus proses shell . Jadi Anda bisa
- baca variabel yang diatur dalam skrip bersumber,
- gunakan fungsi yang ditentukan di dalamnya.
- dan bahkan jalankan fork dan/atau subproses jika skrip melakukan ini.
Saat Anda memanggil sh
, Anda memulai garpu (sub-proses atau anak ) yang menjalankan sesi baru /bin/sh
(yang sering berupa tautan simbolis ke bash
). Dalam hal ini, variabel lingkungan yang disetel oleh subskrip akan dihapus saat subskrip dihentikan.
Perhatian :sh
bisa menjadi symlink ke lain cangkang.
Contoh praktis
Misalnya, jika Anda ingin mengubah direktori kerja saat ini dengan cara tertentu, Anda tidak dapat melakukannya
$ cat <<eof >myCd2Doc.sh
#!/bin/sh
cd /usr/share/doc
eof
$ chmod +x myCd2Doc.sh
Ini tidak akan melakukan apa yang Anda harapkan:
$ cd /tmp
$ pwd
/tmp
$ ~/myCd2Doc.sh
$ pwd
/tmp
karena direktori kerja saat ini adalah bagian dari lingkungan dan myCd2Doc.sh
akan berjalan di subkulit .
Tapi:
$ cat >myCd2Doc.source <<eof
# Shell source file
myCd2Doc() {
cd /usr/share/doc
}
eof
$ . myCd2Doc.source
$ cd /tmp
$ pwd
/tmp
$ myCd2Doc
$ pwd
/usr/share/doc
Lihat mycd
fungsi!! (Dengan penyelesaian bash berdasarkan Associative Array ).
Tingkat eksekusi $SHLVL
$ cd /tmp
printf %b '\43\41/bin/bash\necho This is level \44SHLVL.\n' >qlvl.sh
$ bash qlvl.sh
This is level 2.
$ source qlvl.sh
This is level 1.
Rekursi (saat skrip dijalankan dari dirinya sendiri)
$ cat <<eoqlvl2 >qlvl2.sh
#!/bin/bash
export startLevel recursionLimit=5
echo This is level $SHLVL started:${startLevel:=$SHLVL}.
(( SHLVL < recursionLimit )) && ./qlvl2.sh
eoqlvl2
$ chmod +x qlvl2.sh
$ ./qlvl2.sh
This is level 2 started:2.
This is level 3 started:2.
This is level 4 started:2.
This is level 5 started:2.
$ source qlv2.sh
This is level 1 started:1.
This is level 2 started:1.
This is level 3 started:1.
This is level 4 started:1.
This is level 5 started:1.
Sedikit lagi
$ sed '$a ps --sid $SID fw' qlvl.sh >qlvl3.sh
$ chmod +x qlvl3.sh
$ export SID
$ read SID < <(ps ho sid $$)
$ echo $SID $$
8983 8983
( PID saat ini ($$
==Id proses ) adalah pengenal yang sama dengan SID (ID sesi ). Itu tidak selalu benar.)
$ ./qlvl3.sh
This is level 2.
PID TTY STAT TIME COMMAND
8983 pts/10 Ss 0:00 /bin/bash
10266 pts/10 S+ 0:00 \_ /bin/bash ./qlvl3.sh
10267 pts/10 R+ 0:00 \_ ps --sid 8983 fw
$ . qlvl3.sh
This is level 1.
PID TTY STAT TIME COMMAND
8983 pts/10 Ss 0:00 /bin/bash
10428 pts/10 R+ 0:00 \_ ps --sid 8983 fw
Titik .
adalah alias dari source
. Jadi satu-satunya perbedaan antara dua perintah adalah slash
diganti dengan space
.
Dan final tes:
$ printf %b '\43\41/bin/bash\necho Ending this.\nsle' \
'ep 1;exit 0\n' >finalTest.sh
$ bash finalTest.sh
Ending this.
$ source finalTest.sh
Ending this.
... Anda mungkin melihat berbeda perilaku antara dua sintaks.;-)