Bagaimana cara sintaks memeriksa skrip Bash tanpa menjalankannya?

Jawaban:

380
bash -n scriptname

Mungkin peringatan yang jelas: ini memvalidasi sintaks tetapi tidak akan memeriksa apakah skrip bash Anda mencoba menjalankan perintah yang tidak ada di jalur Anda, seperti ech hellobukan echo hello.

andy
sumber
9
Di manual bash, di bawah "SHELL BUILTIN COMMANDS / set", -n didokumentasikan, dan sebagai awal dari status manpage, bash mengartikan semua opsi karakter tunggal yang setberlaku.
ephemient
24
untuk menambah (bagi saya) peringatan yang tidak jelas, itu juga tidak akan menangkap kesalahan yang disebabkan oleh ruang yang hilang, if ["$var" == "string" ]bukanif [ "$var" == "string" ]
Brynjar
11
@ Brynjar Itu karena itu hanya memeriksa sintaksis. Braket terbuka bukan sintaks, itulah nama fungsi yang akan dijalankan. type [mengatakan "[adalah shell builtin". Ini akhirnya mendelegasikan ke testprogram, tetapi mengharapkan braket penutupan, juga. Jadi itu seperti if test"$var", yang bukan apa yang dimaksud penulis, tetapi secara sintaksis valid (katakanlah $ var memiliki nilai "a", maka kita akan melihat "bash: testa: command not found"). Intinya adalah bahwa secara sintaksis, tidak ada ruang yang hilang.
Joshua Cheek
2
@JoshuaCheek: Builtin [hanya dipanggil dalam kasus ini jika $varterjadi ekspansi ke string kosong . Jika $varmengembang ke non-kosong string [adalah concatenated dengan tali itu dan ditafsirkan sebagai perintah nama (tidak fungsi nama) oleh Bash, dan, ya, itu adalah sintaksis valid, tapi, seperti yang Anda negara, jelas tidak maksud. Jika Anda menggunakan [[alih-alih [, meskipun [[merupakan kata kunci shell (bukan builtin), Anda akan mendapatkan hasil yang sama, karena penggabungan string yang tidak diinginkan masih mengesampingkan pengenalan kata kunci.
mklement0
2
@ JoshuaCheek: Bash masih sintaksis - cek di sini: itu memeriksa sintaks pemanggilan perintah sederhana : ["$var"secara sintaksis ekspresi nama-perintah yang valid ; demikian pula, token ==dan argumen"$string" perintah yang valid . (Umumnya, builtin parsing dengan perintah sintaks, sedangkan - sebagai shell kata kunci - parsing berbeda.) Shell builtin tidak tidak mendelegasikan ke " Program" (utilitas eksternal): , , , semua memiliki builtin versi kedua dan[[[[ testbashdashkshzsh[test, dan mereka tidak memanggil mitra utilitas eksternal mereka.
mklement0
127

Waktu mengubah segalanya. Berikut adalah situs web yang menyediakan sintaksis online untuk memeriksa skrip shell.

Saya menemukan itu sangat kuat mendeteksi kesalahan umum.

masukkan deskripsi gambar di sini

Tentang ShellCheck

ShellCheck adalah alat analisis dan linting statis untuk skrip sh / bash. Ini terutama berfokus pada penanganan tipikal tingkat kesalahan pemula dan menengah dan perangkap di mana shell hanya memberikan pesan kesalahan samar atau perilaku aneh, tetapi juga melaporkan beberapa masalah lebih lanjut di mana kasus sudut dapat menyebabkan kegagalan tertunda.

Kode sumber Haskell tersedia di GitHub!

dvd818
sumber
5
Tip yang bagus; di OSX Anda sekarang dapat juga menginstal CLI shellcheck.net, shellcheck, melalui Homebrew : brew install shellcheck.
mklement0
3
Juga di debian & teman-teman:apt-get install shellcheck
pria lain itu
Untuk Ubuntu terpercaya paket ini harus diinstal dari trusty-backports.
Peterino 4-15
Seperti disebutkan di atas, ketergantungan yang dapat dipercaya dibutuhkan, dan dapat menginstalnya seperti di bawah ini di ubuntu 14.04: sudo apt-get -f install, kemudian: sudo sudo apt-get install shellcheck
zhihong
Ini sangat berguna, tetapi tidak menggunakan parser Bash tapi miliknya sendiri. Dalam kebanyakan kasus ini cukup baik dan dapat mengidentifikasi masalah parsing dan lainnya, tetapi setidaknya ada satu kasus tepi (dan mungkin yang lain saya belum melihat) di mana ia tidak menguraikan dengan cara yang sama.
Daniel H
38

Saya juga mengaktifkan opsi 'u' pada setiap skrip bash yang saya tulis untuk melakukan beberapa pemeriksaan tambahan:

set -u 

Ini akan melaporkan penggunaan variabel yang tidak diinisialisasi, seperti pada skrip berikut 'check_init.sh'

#!/bin/sh
set -u
message=hello
echo $mesage

Menjalankan skrip:

$ check_init.sh

Akan melaporkan sebagai berikut:

./check_init.sh[4]: mesage: Parameter tidak disetel.

Sangat berguna untuk menangkap kesalahan ketik

Diego Tercero
sumber
4
saya mengatur flag-flag ini selalu dalam skrip bash saya, jika melewati ini, ada baiknya untuk "set -o errexit" "set -o nounset" "set -o pipefail"
μολὼν.λαβέ
1 untuk set -uwalaupun ini tidak benar-benar menjawab pertanyaan, karena Anda harus menjalankan skrip untuk mendapatkan pesan kesalahan. Bahkan tidak bash -n check_init.shmenunjukkan peringatan itu
rubo77
23
sh  -n   script-name 

Jalankan ini. Jika ada kesalahan sintaksis dalam skrip, maka ia mengembalikan pesan kesalahan yang sama. Jika tidak ada kesalahan, maka itu keluar tanpa memberikan pesan apa pun. Anda dapat segera memeriksa dengan menggunakan echo $?, yang akan mengembalikan 0konfirmasi berhasil tanpa kesalahan.

Itu bekerja dengan baik untuk saya. Saya berlari di OS Linux, Bash Shell.

Astaga
sumber
1
Meskipun tidak persis terkait dengan cek sintaks bash - menggunakan set -x dan set + x untuk debugging skrip lengkap atau bagian skrip cukup berguna
GuruM
Terima kasih untuk ini tidak tahu tidak tahu tentang -n tetapi yang saya inginkan adalah @GuruM> sh -x test.sh karena itu akan menampilkan output skrip yang
dihasilkan
1
Iya. Saya lupa menyebutkan bahwa Anda dapat melakukan hal berikut Pada baris perintah: 1) bash -x test.sh # ini menjalankan seluruh skrip dalam 'mode debug' 2) set + x; bash test.sh; set -x #setel mode debug hidup / mati sebelum / sesudah skrip dijalankan Dalam skrip: a) #! / bin / bash -x # tambahkan 'mode debug' di atas skrip b) set + x; kode; set -x #add 'mode debug' untuk setiap bagian skrip
GuruM
sh -nmungkin tidak akan memeriksa bahwa skrip tersebut adalah skrip Bash yang valid. Mungkin memberikan negatif palsu. shadalah beberapa varian shell Bourne yang biasanya bukan Bash. Misalnya di Ubuntu Linux realpath -e $(command -v sh)memberi / bin / dash
jarno
4

Saya benar-benar memeriksa semua skrip bash dalam direktori saat ini untuk mengetahui kesalahan sintaksis TANPA menjalankannya menggunakan findalat:

Contoh:

find . -name '*.sh' -exec bash -n {} \;

Jika Anda ingin menggunakannya untuk satu file, cukup edit wildcard dengan nama file tersebut.

Gerald Hughes
sumber
3

perintah nol [titik dua] juga berguna saat debugging untuk melihat nilai variabel

set -x
for i in {1..10}; do
    let i=i+1
    : i=$i
done
set - 
mug896
sumber
itu menggunakan ekspansi parameter
mug896
ini bekerja, karena set -xmenunjukkan setiap baris sebelum dieksekusi
rubo77
1

Ada plugin BashSupport untuk IntelliJ IDEA yang memeriksa sintaksis.

Cengiz
sumber
Tapi itu tidak akan berfungsi jika file Anda tidak diakhiri dengan .shatau ekstensi lain yang terkait dengan skrip Bash, yang merupakan kasus jika Anda menghasilkan skrip menggunakan beberapa alat templating seperti ERB (kemudian berakhir dengan .erb). Silakan pilih youtrack.jetbrains.com/issue/IDEA-79574 jika Anda ingin memperbaikinya!
Greg Dubicki
1

Jika Anda perlu dalam variabel validitas semua file dalam direktori (git pre-commit hook, build skrip lint), Anda dapat menangkap output stderr dari perintah "sh -n" atau "bash -n" (lihat lainnya jawaban) dalam suatu variabel, dan memiliki "jika / lain" berdasarkan itu

bashErrLines=$(find bin/ -type f -name '*.sh' -exec sh -n {} \;  2>&1 > /dev/null)
  if [ "$bashErrLines" != "" ]; then 
   # at least one sh file in the bin dir has a syntax error
   echo $bashErrLines; 
   exit; 
  fi

Ganti "sh" dengan "bash" tergantung kebutuhan Anda

Elvis Ciotti
sumber