Apa perbedaan antara ./ dan sh untuk menjalankan skrip?

71

Saya telah menulis naskah sederhana. Ketika saya menjalankan sh <myscriptname.sh>, saya mendapatkan output yang benar, tetapi ketika saya menjalankan ./<myscriptname.sh>, saya mendapat kesalahan.

Apa perbedaan antara ketika saya melakukannya shdan ./?

mr_eclair
sumber
15
Alih-alih hanya mengatakan, "Saya mendapatkan kesalahan", itu akan membantu jika Anda menempelkan apa yang dikatakan kesalahan.
SpashHit

Jawaban:

67

Saat Anda menjalankan skrip apa pun dengan meneruskan nama file ke program juru bahasa skrip, Anda menjalankan program juru bahasa dengan skrip sebagai argumen yang diteruskan ke dalamnya. Misalnya ini akan terlihat seperti proses 'sh' dengan argumen 'filename.sh'. The shinterpreter membuka file.

Di sisi lain, jika Anda menjalankan skrip itu sendiri, sistem memanggil program penerjemah yang ditentukan dan memasukkan isi skrip. Dalam hal ini prosesnya terlihat seperti 'filename.sh' tanpa argumen.

Anda harus memastikan Anda memiliki garis bang:

#!/bin/bash
# bash script here

Garis bang adalah baris paling pertama dalam skrip dan dimulai dengan dua karakter yang sama #!, inilah yang dibaca sistem ketika mencoba menjalankan skrip dan kemudian sistem meneruskan skrip ke program segera setelahnya. Perhatikan bahwa baris ini tidak ada hubungannya dengan bash dan berfungsi dengan baik untuk python dan perl, meskipun mereka bahasa yang sangat berbeda. Anda akan menggunakan #!/usr/bin/pythonmisalnya dan kemudian mengikutinya dengan kode python.

Setelah Anda memiliki skrip, pastikan Anda telah mengatur izin eksekusi:

chmod a+x filename.sh

Kemudian Anda dapat menjalankan skrip sebagai prosesnya sendiri:

./filename.sh

Atau letakkan file di lokasi yang diketahui dengan nama program yang bagus, sukai /usr/sbindan jalankan dari mana saja:

sudo cp filename.sh /usr/sbin/program-name
program-name

Dan ini benar-benar manfaat praktis menggunakan garis bang dengan izin yang tepat - ini semua tentang penyebaran . Sangat sulit untuk membuat pengguna menjalankan skrip jika mereka harus mengingat program apa yang digunakan untuk menjalankan skrip. Ingatlah untuk memberikan path lengkap ke skrip setiap kali mereka ingin menjalankannya. Di mana menempatkannya sebagai /usr/local/bincontoh, dan membuatnya dapat dieksekusi, dapat menyimpan banyak kesedihan bagi orang-orang yang mencoba menggunakan skrip Anda. Program-program ini kemudian tersedia untuk semua pengguna di komputer Anda.

Ini juga baik untuk identifikasi. Jika Anda masuk ke dalam topprogram, skrip yang dijalankan tanpa bang line hanya akan memiliki nama penerjemah yaitu bash, perlatau python. Tetapi jika skrip dijalankan dengan izin yang tepat, maka nama skrip akan ditampilkan.

Catatan: Jika Anda ingin mendistribusikan skrip yang dapat diakses oleh semua orang, silakan buat halaman manual dan paket deb untuk menginstalnya. Kita perlu mengurangi jumlah skrip acak daring dan meningkatkan jumlah debet yang dapat dihapus instalasinya.

Martin Owens -doctormo-
sumber
1
Anda juga dapat menggunakan folder bin pribadi: buat folder bin untuk folder home Anda logout dan login kembali dan Anda kemudian dapat menjalankan skrip apa pun di folder itu tanpa sh atau ./.
papukaija
Tentu saja, tetapi menambahkan folder rumah Anda ke PATH Anda dapat terlihat sedikit sakit kepala. Lebih baik instal barang. Meskipun ada beberapa pembicaraan tentang penambahan ~ / .local / bin ke path secara default untuk memungkinkan pengguna lokal menginstal paket.
Martin Owens -doctormo-
Perhatikan bahwa penerjemah default adalah bash, bukan sh.
Nathan Osman
1
Jangan menaruh ekstensi pada skrip, terutama ketika Anda memasukkannya PATH.
geirha
1
/usr/local/binmungkin lebih baik /usr/sbin- itu menunjukkan bahwa program ini lokal untuk mesin ini daripada menjadi bagian dari distribusi.
glenn jackman
41

Versi singkat:

  • shadalah interpreter baris perintah (tanda hubung).
    Menjalankan sh my_scriptmembuat tanda hubung menafsirkan skrip.

  • ./mencoba mencari penerjemah mana yang akan digunakan, dengan melihat baris pertama. Misalnya #!/bin/bash, atau bahkan #!/bin/ruby(bukan berlari ruby my_script).

Stefano Palazzo
sumber
7
Ini tidak benar-benar ./menemukan apa-apa, itu adalah metode eksekusi sistem yang melihat dua byte pertama dari file.
Martin Owens -doctormo-
9
Benar. Inilah penjelasan yang sangat panjang tentang itu semua. Saya bersikap pragmatis :)
Stefano Palazzo
Ketika Anda menggunakan shdan file tersebut berisi sha-bang, apakah itu berarti sha-bang akan diabaikan atau akankah ia membuka shell mana shtautannya juga dan kemudian mungkin beberapa shell lain atau apa fungsinya :)?
Ini
5

Perbedaan yang Anda lakukan adalah,

  • dengan sh, Anda menjalankan program yang akan menginterpretasikan garis-garis dalam skrip Anda seperti halnya Anda mengetiknya pada prompt interaktif terminal,

  • dengan ./Anda membuat jalan pintas dengan asumsi bahwa skrip tepat di sini di direktori saat ini Anda duduk DAN itu akan dapat dieksekusi (karena misalnya Anda mengeluarkan chmod +x myscript.sh), menghemat waktu Anda yang tak ternilai untuk masa mendatang :-)

meduz
sumber
3
+1 menjadi satu-satunya yang secara ringkas menyatakan bahwa file tersebut harus dapat dieksekusi.
Mikel
2
Perhatikan bahwa shfile tidak harus dapat dieksekusi.
Ini
3

Ada tiga alasan utama Anda mungkin mendapatkan kesalahan:

  • file tidak dapat
    dijalankan chmod +x <myscriptname.sh>untuk memperbaikinya
  • partisi tidak mengizinkan skrip berjalan (sudah terpasang " noexec")
    menyalin skrip ke/usr/local/bin
  • yang #!baris memiliki kesalahan
    pastikan baris pertama adalah #!/bin/shatau#!/bin/bash

Jika baris pertama Anda terlihat benar, tetapi masih tidak berfungsi, pastikan file tersebut tidak memiliki akhiran garis DOS.

Kesalahan akan terlihat seperti ini:

$ ./myscript.sh
bash: ./myscript.sh: /bin/bash^M: bad interpreter: No such file or directory

Anda dapat memperbaikinya dengan menjalankan dos2unix <myscriptname.sh>, atau jika Anda tidak memilikinya
perl -p -i -e 's/\r\n$/\n/' <myscriptname.sh>,.

Mikel
sumber
0

Dan jawabannya adalah sh adalah nama untuk shell yang sangat populer. Namun ketinggalan jaman dan digantikan oleh orang lain. Saat ini sh dikaitkan dengan cangkang lain yang terpasang pada mesin. misal saya sudah bash putt di sana. Menjalankan sembarang shell dari sh biasanya memicu beberapa mode 'kompatibilitas' dengan perilaku 'shell' asli.

Jadi solusinya cukup sederhana. Lihat apa yang ada di balik perintah sh (ls -al / bin / sh), dan letakkan #! / Bin / whatever_you_find_there sebagai baris pertama (atau jika ada sesuatu seperti itu dalam skrip Anda, editlah).

Dan alternatifnya mungkin ada beberapa bug dalam skrip itu sendiri. Seperti ketergantungan yang dipenuhi oleh sh, tetapi bukan penerjemah yang benar-benar digunakan.

przemo_li
sumber
0
mkdir ~/bin ; cp myscript.sh ~/bin/

echo "export PATH="$PATH:/home/$USER/bin" >> ~/.profile ; source ~/.profile ; 

Tidak /usr/sbin, itu untuk alat administratif yang tidak penting, /usr/local/binadalah pilihan yang lebih baik jika Anda tidak ingin memilikinya ~/bin/, tetapi menghindari sudosebisa mungkin disarankan.

Joey1978
sumber
Di Ubuntu, defaultnya ~/.profilesudah memiliki kode untuk menambahkan ~/bin, jika ada, untuk PATH. Pada catatan lain, jangan letakkan ekstensi pada skrip.
geirha
1
Saya mereferensikan <myscriptname.sh>, tetapi apa alasan untuk tidak meletakkan ekstensi pada skrip? Saya biasanya melakukannya karena memiliki file teks biasa terlihat seperti itu membuat saya tidak mencoba mengedit biner yang saya juga simpan di ~ / bin /. ( ls ~/bin/|wc -l = 428) Saya menaruh banyak barang di sana;)
Joey1978
Bayangkan Anda menulis naskah untuk mencapai tugas tertentu. Kemudian Anda menyadari bahwa menulis skrip khusus ini dengan python akan membuatnya jauh lebih efisien, sehingga Anda menulis ulangnya dengan python. Sekarang kamu punya dua pilihan. 1) Tinggalkan ekstensi .sh yang sekarang sangat menyesatkan, atau 2) ganti nama skrip dan cari dan ganti semua penggunaan skrip untuk menggunakan nama baru. Jika Anda melihat skrip /bindan /usr/binAnda akan melihat mereka tidak menggunakan ekstensi.
geirha