Sumber daya untuk pemrograman shell portabel

65

Sumber daya apa yang ada untuk pemrograman shell portabel? Jawaban utamanya adalah untuk menguji pada semua platform yang ditargetkan, tetapi itu jarang praktis.

Spesifikasi POSIX / Single UNIX adalah awal, tetapi tidak memberi tahu Anda apa tingkat dukungan dari setiap implementasi, atau apa ekstensi umum yang ada. Anda dapat membaca dokumentasi setiap implementasi, tetapi itu sangat memakan waktu dan tidak sepenuhnya akurat.

Saya kira bagi saya bahwa format ideal adalah semacam versi POSIX yang dianotasi komunitas, di mana setiap fitur dijelaskan oleh tingkat dukungannya di antara implementasi yang berbeda. Apakah ada hal seperti itu? Atau adakah sumber daya lain yang bermanfaat?

Misalnya, ada halaman portabilitas shell Sven Mascheck , tetapi ini hanya tentang elemen sintaksis dan beberapa built-in, dan hanya mencakup shell lama. Saya mencari sumber yang lebih komprehensif.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
2
NB Tolong jangan jawab di sini hanya untuk mengutip dokumen kesesuaian satu implementasi tertentu. Jika Anda memilikinya, wiki tag yang sesuai akan menjadi tempat yang baik.
Gilles 'SO- stop being evil'
1
Seseorang perlu menambang riwayat revisi untuk autoconfdan Metaconfig(Perl, rn) dan mengumpulkan semua trik dan komentar penjelasan mereka di satu tempat.
geekosaur
@geekosaur: Saran bagus. Saya tidak pernah melihat internal autoconf, adakah yang bisa digunakan sebagai panduan saat menulis skrip sendiri? Jika demikian, ini akan menjadi jawaban yang baik untuk pertanyaan saya, bahkan jika itu bukan jawaban yang pasti.
Gilles 'SO- stop being evil'
5
Saya yakin Anda berdua dapat menemukannya dengan mudah, tetapi untuk kepentingan orang lain yang mengikuti utas ini, berikut ini tautan ke halaman yang relevan dari manual autoconf: gnu.org/software/hello/manual/autoconf/Portable- Shell.html
J. Taylor

Jawaban:

32

Manual autoconf memiliki bagian tentang pemrograman shell portabel .

Meskipun itu tidak secara khusus menargetkan POSIX, itu mungkin koleksi paling lengkap dari apa yang harus dilakukan dan tidak dilakukan ketika mencoba untuk menulis kode shell portabel.

Riccardo Murri
sumber
3
Itu salah satu sumber daya terbaik dan dibangun saat menulis kode dalam M4 yang harus menghasilkan kode shell yang portabel melintasi sebanyak mungkin shell.
Tim Post
6

Selain dashdan posh, ada bournesh(atau bsh), Heirloom Bourne Shell , yang dapat digunakan untuk mendeteksi Bashism .

Proyek Heirloom juga termasuk "The Heirloom Toolchest", koleksi lebih dari 100 utilitas Unix standar (yang dapat berfungsi sebagai titik awal untuk membandingkan opsi baris perintah).

ralf
sumber
2
Perhatikan bahwa cangkang Bourne bukan cangkang POSIX, menjadikan skrip Anda portabel untuk cangkang Bourne akan berarti menurunkan sintaks skrip Anda dari bahasa sh POSIX standar ke penyebut umum antara itu dan sintaksis cangkang Bourne. Tidak sepadan dengan pendapat kecuali Anda ingin menjadi portabel untuk sistem kuno (atau Solaris 10 dan sebelumnya dan Anda tidak memiliki pilihan untuk menggunakan sh standar yang ada di / usr / xpg4 / bin di sana).
Stéphane Chazelas
5

Mirip dengan jawaban ini , coba jalankan skrip Anda di posh .

Juga, jangan lupa untuk mengatur POSIXLY_CORRECTvariabel lingkungan ke true, karena ini menyebabkan banyak program (tidak hanya shell) untuk lebih ketat mematuhi standar POSIX.

Philomath
sumber
4

Menulis skrip Anda menggunakan tanda hubung mungkin merupakan awal.

glenn jackman
sumber
3
Pengujian dengan dash adalah minimum untuk menghindari ketergantungan yang tidak disengaja pada fitur ksh / bash, tapi saya lebih dari itu: mengetahui tentang kekurangan di shell lain (mis. Penanganan perangkap zsh yang buruk), dan terutama di utilitas shell (mis. findMasih OpenBSD masih belum diimplementasikan -exec +).
Gilles 'SANGAT berhenti menjadi jahat'
FWIW, OpenBSD findmelakukannya -exec utility {} +sekarang.
Kusalananda
2

Untuk sedikit memperluas, Anda dapat mencoba paket checkbashismsDebian / Ubuntu devscripts.

Ini tidak sempurna, tetapi memiliki manfaat sebagai titik awal yang ada. Sebagai contoh, ia tidak melihat gangguan klasik dengan sed/ findmengenai GNU vs BSD / perbedaan lainnya.

Secara default, ini berorientasi pada Debian + dash, -pflag dapat berguna untuk kasus Anda.

shellholic
sumber
2

Hari ini, Anda biasanya dapat menemukan shell POSIX pada suatu sistem, dan dengan demikian umumnya berarti Anda dapat skrip dalam bahasa POSIX (modulo menjalankan bug kepatuhan).

Satu-satunya masalah adalah bahwa /bin/shkadang-kadang bukan shell POSIX. Dan Anda harus mengkodekan #!baris menjadi skrip yang akan berperilaku sebagai executable yang bagus; Anda tidak bisa hanya meminta pengguna untuk meneliti masalah dan kemudian memanggil skrip Anda sebagai /path/to/posix/shell myscript.

Jadi, caranya adalah dengan menggunakan fitur POSIX dalam skrip Anda, tetapi buat skrip tersebut secara otomatis menemukan shell POSIX. Salah satu cara untuk melakukannya adalah seperti ini:

#!/bin/sh

# At this point, we may be running under some old shell
# we have to tread carefully.

# note how we use test rather than [ ] syntax and avoid
# depending on test with no argument producing a failure;
# i.e. "test $posix_shell".

if ! test x$posix_shell = x ; then
  # the three possible shell paths are just an example;
  # please extend as necessary.

  for shell in /usr/xpg4/bin/sh /bin/bash /usr/bin/bash ; do
    if test -x $shell ; then
       posix_shell=$shell
    fi
  done
  if test x$posix_shell = x ; then
    echo "no POSIX shell found"
    exit 1
    # or we could avoid bailing here and just fall back on /bin/sh:
    # echo "falling back on /bin/sh: cross your fingers that it works"
    # posix_shell=/bin/sh
  fi
  export posix_shell

  # plain "$@" is broken in ancient shells! 
  # I seem to recall ${@+"$@"}: not sure if that's the right trick.

  exec $posix_shell $0 ${@+"$@"}  # can we count on exec in legacy shells? 
fi

# phew, at this point in the script we have been re-executed and are
# being interpreted by some reasonably modern shell. We can use $(...)
# command substitution, and other features.

Ada beberapa pendekatan lain, seperti pembuatan kode. Boostrap skrip Anda dengan skrip kecil yang mengambil badan file skrip tanpa #! baris, dan menambahkan satu.

Hal terburuk yang dapat Anda lakukan adalah mulai menulis seluruh skrip sedemikian rupa sehingga dijalankan pada cangkang Bourne mulai tahun 1981. Ini hanya diperlukan jika Anda harus menulis untuk sistem yang tidak benar-benar tidak memiliki cangkang lain. .

Kaz
sumber