it-swarm-id.com

Berbagai cara untuk menjalankan skrip Shell

Ada beberapa cara untuk menjalankan skrip, yang saya tahu adalah:

/path/to/script # using the path (absolute or relative)
. script        # using the . (dot)
source script   # using the `source` command

Apakah lebih dari ini? Apa perbedaan di antara mereka? Apakah ada situasi yang harus saya gunakan satu dan bukan yang lain?

44
phunehehe

Cara lain adalah dengan memanggil juru bahasa dan meneruskan path ke skrip untuk itu:

/bin/sh /path/to/script

Titik dan sumbernya setara. (EDIT: tidak, mereka tidak: seperti yang ditunjukkan KeithB dalam komentar pada jawaban lain, "." Hanya bekerja di shell terkait bash, di mana "source" bekerja di shell terkait bash dan csh.) Ia menjalankan skrip di -place (seolah-olah Anda menyalin dan menempelkan skrip di sana). Ini berarti bahwa setiap fungsi dan variabel non-lokal dalam skrip tetap ada. Ini juga berarti jika skrip melakukan cd ke direktori, Anda akan tetap berada di sana ketika selesai.

Cara lain menjalankan skrip akan menjalankannya dalam subkulitnya sendiri. Variabel dalam skrip tidak masih hidup saat selesai. Jika skrip mengubah direktori, maka skrip tidak memengaruhi lingkungan panggilan.

/ path/to/script dan/bin/sh script sedikit berbeda. Biasanya, sebuah skrip memiliki "Shebang" di awal yang terlihat seperti ini:

#! /bin/bash

Ini adalah jalan menuju juru bahasa skrip. Jika ia menentukan juru bahasa yang berbeda dari yang Anda lakukan ketika Anda menjalankannya, maka itu mungkin berperilaku berbeda (atau mungkin tidak bekerja sama sekali).

Misalnya, skrip Perl dan Ruby dimulai dengan (masing-masing):

#! /bin/Perl

dan

#! /bin/Ruby

Jika Anda menjalankan salah satu skrip tersebut dengan menjalankan /bin/sh script, maka mereka tidak akan bekerja sama sekali.

Ubuntu sebenarnya tidak menggunakan bash Shell, tetapi yang sangat mirip disebut dasbor. Skrip yang memerlukan bash mungkin berfungsi sedikit salah ketika dipanggil dengan melakukan /bin/sh script karena Anda baru saja memanggil skrip bash menggunakan penerjemah dasbor.

Perbedaan kecil lainnya antara memanggil skrip secara langsung dan meneruskan jalur skrip ke penerjemah adalah bahwa skrip harus ditandai dapat dieksekusi untuk menjalankannya secara langsung, tetapi tidak menjalankannya dengan meneruskan jalur ke interpreter.

Variasi kecil lainnya: Anda dapat mengawali salah satu cara ini untuk menjalankan skrip dengan eval, jadi, Anda dapat memilikinya

eval sh script
eval script
eval . script

dan seterusnya. Sebenarnya tidak mengubah apa-apa, tapi saya pikir saya akan memasukkannya untuk ketelitian.

32
Shawn J. Goff

Kebanyakan orang men-debug skrip Shell dengan menambahkan tanda debug debuging berikut ke skrip:

set -x     # Print command traces before executing command.
set -v     # Prints Shell input lines as they are read.
set -xv    # Or do both

Tetapi ini berarti Anda harus membuka file dengan editor (dengan asumsi Anda memiliki izin untuk mengedit file), menambahkan baris seperti set -x, simpan file, lalu jalankan file. Kemudian ketika Anda selesai, Anda harus mengikuti langkah-langkah yang sama dan menghapus set -x, dll. Ini bisa membosankan.

Alih-alih melakukan semua itu, Anda dapat mengatur flag debugging pada commandline:

$ bash -x ~/bin/ducks
+ du -cks -x dir1 dir2 dir3 file1 file2 file3
+ sort -n
+ tail .ducks
123 etc
424 bin
796 total



$ sh -xv ~/bin/ducks  
#!/usr/bin/env bash

# Find the disk hog
# Borrowed from http://oreilly.com/pub/h/15
...
...
9
Stefan Lasiewski

Shawn J. Goff membuat banyak poin bagus, tetapi tidak memasukkan keseluruhan cerita:

Ubuntu sebenarnya tidak menggunakan bash Shell, tetapi yang sangat mirip disebut dasbor. Skrip yang memerlukan bash mungkin berfungsi sedikit salah ketika dipanggil dengan melakukan /bin/sh script karena Anda baru saja memanggil skrip bash menggunakan penerjemah dasbor.

Banyak skrip sistem (seperti di init.d, di/etc dan sebagainya) memiliki _ Shebang #!/bin/sh, tapi /bin/sh sebenarnya adalah tautan simbolis ke Shell lain - di masa lalu /bin/bash, saat ini /bin/dash. Tetapi ketika salah satu dari mereka dipanggil sebagai /bin/sh, mereka berperilaku berbeda, yaitu mereka tetap pada mode kompatibilitas-POSIX.

Bagaimana mereka melakukan ini? Yah, mereka memeriksa bagaimana mereka dipanggil.

Bisakah shellscript itu sendiri menguji bagaimana itu dipanggil, dan melakukan hal-hal yang berbeda, tergantung pada itu? Ya bisa. Jadi cara Anda memintanya selalu dapat menyebabkan hasil yang berbeda, tetapi tentu saja jarang dilakukan untuk mengganggu Anda. :)

Sebagai aturan praktis: Jika Anda mempelajari Shell seperti bash, dan menulis perintah dari tutorial bash, tulis #!/bin/bash dalam judul, bukan #!/bin/sh, kecuali jika disebutkan sebaliknya. Jika tidak, perintah Anda mungkin gagal. Dan jika Anda belum menulis skrip sendiri, jalankan secara langsung (./foo.sh, bar/foo.sh) alih-alih menebak Shell (sh foo.sh, sh bar/foo.sh). Shebang harus memanggil Shell yang tepat.

Dan inilah dua jenis doa lainnya:

cat foo.sh | dash
dash < foo.sh
7
user unknown

. dan source sama dengan mereka tidak menghasilkan subproses tetapi menjalankan perintah di Shell saat ini. Ini penting ketika skrip mengatur variabel lingkungan atau mengubah direktori kerja saat ini.

Menggunakan path atau memberikannya ke /bin/sh membuat proses baru di mana perintah dijalankan.

5
mouviciel
sh script
bash script

Saya merenungkan jika ada lebih banyak ...

. dan source adalah sama. Setelah eksekusi, setiap perubahan lingkungan di script akan disimpan. Biasanya, ini akan digunakan untuk sumber perpustakaan Bash, sehingga perpustakaan dapat digunakan kembali dalam banyak skrip yang berbeda.

Juga cara yang baik untuk menyimpan direktori saat ini. Jika Anda mengubah direktori dalam skrip, itu tidak akan diterapkan di Shell yang Anda jalankan skrip itu. Tetapi jika Anda sumber untuk menjalankannya, setelah skrip keluar, direktori saat ini akan disimpan.

2
livibetter

. dan sumber sedikit berbeda di zsh setidaknya (itulah yang saya gunakan) karena

source file

Bekerja, sementara

. file

tidak, itu perlu

. ./file
1
bollovan
. ./filename
# ( dot space dot slash filename )

Menjalankan skrip di Shell saat ini ketika direktori tidak di jalur.

1
jrh_enginnering

Apakah " serland exec " dihitung sebagai cara yang berbeda? Exec Userland memuat kode dan menjalankannya tanpa menggunakan panggilan sistem execve ().

1
Bruce Ediger