Bagaimana menjalankan skrip shell pada konsol Unix atau terminal Mac?

507

Saya tahu, lupakan dan pelajari kembali. Saatnya menuliskannya.

PA
sumber
15
menulis kereta upvote sampai ke stasiun reputasi
DivideByZer0
tidak akan mengungguli hanya untuk mengagumi kesalahan luar biasa yang Anda dapatkan di sana!
BRHSM

Jawaban:

942

Untuk menjalankan shskrip yang tidak dapat dieksekusi , gunakan:

sh myscript

Untuk menjalankan bashskrip yang tidak dapat dieksekusi , gunakan:

bash myscript

Untuk memulai file yang dapat dieksekusi (file apa saja dengan izin yang dapat dieksekusi); Anda cukup menentukannya menurut jalurnya:

/foo/bar
/bin/bar
./bar

Untuk membuat skrip dapat dieksekusi, berikan izin yang diperlukan:

chmod +x bar
./bar

Ketika sebuah file dapat dieksekusi, kernel bertanggung jawab untuk mencari tahu bagaimana cara membukanya. Untuk non-binari, ini dilakukan dengan melihat baris pertama file. Itu harus mengandung hashbang:

#! /usr/bin/env bash

Hashbang memberitahu kernel program apa yang harus dijalankan (dalam hal ini perintah /usr/bin/envdijalankan dengan argumen bash). Kemudian, skrip diteruskan ke program (sebagai argumen kedua) bersama dengan semua argumen yang Anda berikan skrip sebagai argumen berikutnya.

Itu berarti setiap skrip yang dapat dieksekusi harus memiliki hashbang . Jika tidak, Anda tidak memberitahu kernel apa yang , dan karena itu kernel tidak mengetahui program apa yang digunakan untuk menginterpretasi itu. Bisa jadi bash, perl, python, sh, atau sesuatu yang lain. (Pada kenyataannya, kernel akan sering menggunakan shell default pengguna untuk menginterkrip file, yang sangat berbahaya karena mungkin tidak menjadi penerjemah yang tepat sama sekali atau mungkin dapat menguraikan beberapa di antaranya tetapi dengan perbedaan perilaku yang halus seperti kasus antara shdan bash).

Sebuah catatan /usr/bin/env

Paling umum, Anda akan melihat poni hash seperti:

#!/bin/bash

Hasilnya adalah bahwa kernel akan menjalankan program /bin/bashuntuk menafsirkan skrip. Sayangnya, bashtidak selalu dikirimkan secara default, dan itu tidak selalu tersedia di /bin. Sementara pada mesin Linux biasanya, ada berbagai mesin POSIX lain di mana bashdikirimkan di berbagai lokasi, seperti /usr/xpg/bin/bashatau /usr/local/bin/bash.

Untuk menulis skrip bash portabel, oleh karena itu kita tidak dapat mengandalkan hard-coding lokasi bashprogram. POSIX sudah memiliki mekanisme untuk menangani dengan itu: PATH. Idenya adalah bahwa Anda menginstal program Anda di salah satu direktori yang ada PATHdan sistem harus dapat menemukan program Anda ketika Anda ingin menjalankannya dengan nama.

Sayangnya, Anda tidak bisa hanya melakukan ini:

#!bash

Kernel tidak akan (sebagian mungkin) melakukan PATHpencarian untuk Anda. Ada sebuah program yang dapat melakukan PATHpencarian untuk Anda, itu disebut env. Untungnya, hampir semua sistem memiliki envprogram yang diinstal /usr/bin. Jadi kami mulai envmenggunakan lintasan hardcode, yang kemudian melakukan PATHpencarian bashdan menjalankannya sehingga dapat menafsirkan skrip Anda:

#!/usr/bin/env bash

Pendekatan ini memiliki satu kelemahan: Menurut POSIX, hashbang dapat memiliki satu argumen . Dalam hal ini, kami menggunakan bashsebagai argumen untuk envprogram. Itu berarti kita tidak punya ruang tersisa untuk mengajukan argumen bash. Jadi tidak ada cara untuk mengonversi sesuatu seperti #!/bin/bash -exuke skema ini. Anda harus memasukkan set -exuhashbang sebagai gantinya.

Pendekatan ini juga memiliki keuntungan lain: Beberapa sistem mungkin mengirim dengan /bin/bash, tetapi pengguna mungkin tidak menyukainya, mungkin menemukan itu buggy atau ketinggalan zaman, dan mungkin telah menginstal sendiri di bashtempat lain. Ini sering terjadi pada OS X (Macs) di mana Apple mengirimkan barang usang /bin/bashdan pengguna menginstal yang terbaru /usr/local/bin/bashmenggunakan sesuatu seperti Homebrew. Saat Anda menggunakan envpendekatan yang melakukan PATHpencarian, Anda memasukkan preferensi pengguna ke dalam akun dan menggunakan bash pilihannya di atas yang dikirimkan sistemnya.

lununath
sumber
66
Terima kasih telah meluangkan waktu untuk menulis jawaban yang bagus untuk pertanyaan sederhana.
PA
5
Jika saya menggunakan zshshell saya, apakah saya akan menggunakan hashbang #! /usr/bin/env zsh?
stefmikhail
6
@stefmikhail: Tidak masalah penafsir shell mana yang Anda gunakan untuk menjalankan skrip, Anda harus menggunakan #! /usr/bin/env zshjika (dan hanya jika) kode di dalam skrip harus dieksekusi oleh Z shell.
Johnsyweb
1
+1 untuk penjelasan. Saya cenderung lupa tetapi mengetahui arti perintah akan membantu saya mengingat kembali.
Angelin Nadar
2
@Carpetsmoker Ini benar, dan tidak terbatas pada hashbang. skrip bash harus selalu menggunakan akhiran baris UNIX jika tidak, argumen terakhir dari setiap perintah akan ditambahkan, sama seperti nama perintah hashbang.
lhunath
80

Untuk memulai skrip shell 'file.sh':

sh file.sh

bash file.sh

Opsi lain adalah mengatur izin yang dapat dieksekusi menggunakan perintah chmod:

chmod +x file.sh

Sekarang jalankan file .sh sebagai berikut:

./file.sh
PA
sumber
16

Untuk shell bourne:

sh myscript.sh

Untuk bash:

bash myscript.sh

sumber
Terima kasih telah menjawab pertanyaan yang sangat jelas ini. Untuk orang Mac seperti saya, mudah untuk melupakan perintah Unix lama di antara pangkuan.
PA
10

Jika Anda ingin skrip dijalankan di shell saat ini (mis. Anda ingin skrip dapat memengaruhi direktori atau lingkungan Anda), Anda harus mengatakan:

. /path/to/script.sh

atau

source /path/to/script.sh

Catatan yang /path/to/script.shdapat bersifat relatif, misalnya . bin/script.shmenjalankan script.shdalam bindirektori di bawah direktori saat ini.

Chas. Owens
sumber
7
Berhati - hatilah saat sumber atau dot'ing dengan nama path yang berhubungan. Anda harus selalu memulainya dengan ./ Jika Anda tidak melakukan ini, dan pathname relatif tidak mengandung garis miring, Anda akan mencari sumber di PATH, SEBELUM sesuatu di direktori saat ini! Sangat berbahaya karena disalahgunakan.
lhunath
0

Pertama, beri izin untuk eksekusi: -
chmod +x script_name

  1. Jika skrip tidak dapat dieksekusi: -
    Untuk menjalankan file skrip sh: -
    sh script_name
    Untuk menjalankan file skrip bash: -
    bash script_name
  2. Jika skrip dapat dieksekusi: -
    ./script_name

CATATAN : -Anda dapat memeriksa apakah file dapat dieksekusi atau tidak dengan menggunakan 'ls -a'

Vineet Jain
sumber
0

Ekstensi file .command ditugaskan ke Terminal.app. Mengklik dua kali pada file .command akan menjalankannya.

benwiggy
sumber
0

Sedikit tambahan, untuk menjalankan juru bahasa dari folder yang sama, masih menggunakan #! Hashbang dalam skrip.

Sebagai contoh, sebuah executable php7.2 yang disalin dari / usr / bin ada dalam folder di sepanjang skrip halo .

#!./php7.2
<?php

echo "Hello!"; 

Untuk menjalankannya:

./hello

Yang berperilaku sama dengan:

./php7.2 hello
NVRM
sumber