Mengapa saya harus menaruh sh sebelum menjalankan file .sh?

16

Ketika saya ingin menjalankan .shfile di Terminal, saya harus meletakkannya shdi depan.

Apakah ada cara untuk menghindari ini, dan dengan demikian menghemat pengetikan?

Lebih dari Lima
sumber
3
Saya membuat folder di ~ / bin untuk meletakkan skrip shell saya dan meletakkannya di $ PATH saya dan juga melampirkan Folder Action ke folder ~ / bin untuk secara otomatis mengatur izin eksekusi karena itu sangat mudah untuk dilupakan.
Kaydell

Jawaban:

22

Jika Anda menjalankan skrip dari shell, Anda sebenarnya tidak memerlukan #!/bin/shshebang seperti yang dijabarkan dalam jawaban ini –semuanya sistem Unix-like yang saya gunakan, termasuk OS X, akan default ke /bin/shjika tidak ada penerjemah yang ditentukan secara khusus ( meskipun itu ide yang bagus karena non-shell tidak akan tahu cara menjalankan skrip Anda kecuali Anda memberikan shebang.)

Anda juga tidak perlu .shekstensi. Anda lakukan perlu untuk mengatur hak akses executable, misalnya

$ chmod +x script.sh

(Ini $adalah shell prompt; Saya menggunakannya untuk menggambarkan perintah yang Anda berikan pada shell interaktif. Jangan mengetiknya!)

Namun, saya pikir apa kebingungan Anda adalah bahwa Anda telah membuat skrip, misalnya script.sh, di direktori saat ini, dan mencoba untuk mengeksekusinya dengan hanya mengetik script.sh. misalnya

$ cat >script.sh
echo hello, world
^D
$ chmod +x script.sh
$ script.sh
-bash: script.sh: command not found

( ^DBerarti control- D. Anda akan menemukan notasi ini di banyak luncuran menggunakan Unix.)

Fakta bahwa script.shdalam kasus ini adalah skrip shell hanya setengah dari masalah; masalah Anda yang sebenarnya adalah bahwa, secara default, shell tidak akan mencari direktori saat ini untuk sebuah program. Namun, ini berfungsi:

$ sh script.sh
hello, world

karena shmengambil naskah sebagai argumen.

Anda dapat menjalankan script-atau, lagi, setiap executable-dalam direktori saat ini, jika ditandai executable (yaitu chmod +x), dengan menentukan bahwa Anda ingin menjalankan satu di direktori saat ini:

$ ./script.sh
hello, world

Anda juga dapat memindahkan skrip ke direktori di PATH. Saya sarankan /usr/local/binuntuk ini jika skrip Anda dimaksudkan untuk digunakan di seluruh sistem, atau bindirektori di rumah Anda jika skrip hanya untuk Anda. Yang terakhir mengharuskan Anda untuk menambahkan $HOME/bin, yang meluas ke direktori bin baru Anda, ke Anda PATHdengan menambahkan baris berikut ke .profiledalam direktori home Anda:

PATH=$HOME/bin:$PATH
export PATH

Akhirnya, Anda bisa, jika mau, benar-benar menambahkan direktori saat ini ke direktori Anda PATH, yang akan memungkinkan Anda untuk hanya pergi ke direktori yang berisi script.sh–atau semua executable lainnya– dan ketik

$ script.sh

untuk melaksanakannya. Namun, saya tidak merekomendasikan praktik ini , karena penyerang sekarang dapat menipu Anda untuk menjalankan eksekusi yang sewenang-wenang dengan menjatuhkan skrip yang dapat dieksekusi (bernama, katakan, ls) ke direktori tempat Anda akan berada. Namun, jika Anda benar - benar ingin melakukannya, tambahkan saja yang berikut ke .profile:

PATH=.:$PATH
export PATH
zigg
sumber
Menempatkan '.' di akhir $ PATH alih-alih dari awal dan sekarang Anda tidak perlu khawatir tentang hantu 'ls'. (Meskipun jika seseorang dapat masuk ke sistem Anda, Anda memiliki masalah yang lebih besar.)
TJ Luoma
2
@TJ, tetapi Anda jangan perlu khawatir tentang hal-hal seperti slatau llsatau l... yaitu, kesalahan ketik. Tinggalkan .saja $PATH. Juga, Anda mungkin tidak (atau tidak seharusnya) mempercayai semua orang di sistem Anda. Sebagai contoh, misalkan ada beberapa exploit yang memungkinkan penyerang untuk menjatuhkan file sewenang-wenang ke beberapa direktori, tetapi mereka membutuhkan Anda untuk mengeksekusi file itu agar meningkat ke exploit yang lebih baik (mis., Kumpulkan data dan telepon rumah). Pertahanan secara mendalam!
Reid
@TJLuoma Apa yang dikatakan @ Reid, dan perlu diingat bahwa ada banyak kasus penggunaan untuk sistem Unix di luar desktop OS X pribadi. Belum pernah mencobanya, tetapi saya bertaruh bahkan akun tamu dapat meninggalkan salah satu dari barang-barang itu di /tmpatau direktori lain yang dapat ditulis oleh dunia.
zigg
Jika Anda menggunakan sistem di mana orang lain memiliki akses ke direktori yang Anda gunakan, Anda punya masalah yang lebih besar.
TJ Luoma
@TJLuoma Sebaiknya Anda tidak pernah menggunakan banyak akun di sistem Unix mana pun. /tmpet al. datang dengan wilayah itu.
zigg
10

Anda tidak perlu menelepon shjika file skrip ditandai sebagai executable. Dalam hal ini, Anda dapat memanggilnya nama saya sama seperti Anda akan perintah lain dari shell yang ada


Agar sepenuhnya layak, Anda ingin melakukan dua hal:

  1. Edit skrip Anda untuk memasukkan arahan shebang di bagian atas skrip Anda:

    #!/bin/sh

    ... Itu akan memberi tahu shell penerjemah mana yang akan digunakan untuk menjalankan skrip; dalam hal ini, /bin/shexecutable.

  2. Tandai skrip sebagai dieksekusi oleh Anda dengan perintah chmod :

    chmod u+x scriptname.sh

Setelah Anda melakukan keduanya, Anda harus dapat menjalankan skrip Anda dengan mengetikkan nama file skrip Anda pada baris perintah. Anda harus berada di direktori yang sama dengan skrip Anda, kecuali jika Anda juga mengambil langkah menambahkan folder yang berisi ke variabel PATH Anda . Jika Anda tidak peduli shell apa yang menjalankan skrip, Anda tidak perlu langkah satu untuk menentukan shtetapi seringkali lebih baik untuk lebih tepat dan mengatur "shebangsh".

Chris W. Rea
sumber
Shebangs sebenarnya tidak diperlukan /bin/sh, meskipun tidak sakit.
zigg
@zigg - Anda benar. Saya harap Chris tidak keberatan dengan suntingan saya ... Nuke atau edit ulang seperti yang diinginkan: -0
bmike
@bmike Hasil edit berfungsi untuk saya. Sedangkan untuk shebangs, kebiasaan saya adalah selalu menentukan karena saya dulu menulis banyak kshskrip di masa saya di HP-UX - tetapi ada baiknya mengetahui bahwa itu tidak sepenuhnya diperlukan.
Chris W. Rea
1
Saya pikir saya harus mundur dari pernyataan saya sebelumnya tentang perlunya shebang (meskipun sisa jawaban saya masih berdiri.) Anda dapat menjalankan skrip tanpa-shebang dari shell, tetapi jika Anda menggunakan execsyscall, Anda mendapatkan ENOEXEC(kesalahan format exec ). Maaf soal itu, @bmike, @ ChrisW.Rea. Saya akan mengedit jawaban saya sekarang.
zigg