Jak mogę przetestować zgodność skryptów powłoki z POSIX?

72

Biorąc pod uwagę, że POSIX jest najbliższy wspólnemu standardowi wśród wszystkich jednorożców, interesuje mnie, czy istnieje powłoka, która obsługuje go wyłącznie. Chociaż większość współczesnych powłok zapewnia obsługę POSIX (i bez problemu uruchomi skrypty zgodne z POSIX), nie radzą sobie dobrze z wskazywaniem funkcji niezgodnych.

Czy jest jakaś powłoka, która implementuje tylko POSIX i POSIX, w taki sposób, że generowałaby błąd dla dowolnej niezgodnej funkcji?

EDYCJA Chcę wyjaśnić, że nie pytam o ogólne wskazówki dotyczące pisania przenośnych skryptów powłoki. Pokrewne pytanie wspomniane w komentarzach już to obejmowało. Pomyślałem o tym pytaniu, gdy dowiedziałem się, że bashma --posixopcję, ale tylko po to, aby odkryć, że ma ona wpływ tylko na niektóre zachowania związane z inicjalizacją, które nie są dokładnie tym, czego szukam.

rahmu
źródło
@Gilles: Może powinienem wspomnieć, że natknąłem się na to pytanie, ale tylko jedna odpowiedź sugerowała testowanie dash. Wspomniałem o przenośności jako ogólnym kontekście mojego pytania, ale to nie była jego prawdziwa intencja.
rahmu
Jasne, chciałem połączyć dwa pytania, ponieważ prawdopodobnie zainteresują one te same osoby. W żadnym wypadku nie są duplikatami. Nawiasem mówiąc, posh jest lepszym testem zgodności z POSIX niż dash.
Gilles
2
busybox jest dość zbliżony do POSIX i tylko POSIX. Jedną z rzeczy, które mogą cię potknąć, jest to, że jeśli zainstalujesz również inne pakiety (takie jak diffutils), może to dodać funkcje. Zamówienie linux alpejskie livecd „s, która zaczyna cię z czystym środowisku BusyBox. Alpine używa biblioteki C musl, więc nie dostajesz rozszerzeń GNU, które mogą dodawać funkcje, takie jak rozszerzone wyrażenia regularne.
Michael Fox

Odpowiedzi:

37

Niestety „przenośny” jest zwykle silniejszym wymaganiem niż „zgodny z POSIX” dla skryptów powłoki. Oznacza to, że napisanie czegoś, co działa na dowolnej powłoce POSIX, nie jest zbyt trudne, ale trudniej jest uruchomić go na dowolnej powłoce w świecie rzeczywistym.

Możesz zacząć od zainstalowania każdej powłoki w menedżerze pakietów, w szczególności poshdźwięków Debiana, takich jak chcesz (zgodna z polityką zwykła skorupa). Polityką Debiana jest POSIX z kilkoma wyjątkami ( echo -nokreślone, local...).

Poza tym testy muszą obejmować kilka powłok (szczególnie / bin / sh) na wielu platformach. Testuję na Solarisie (/ bin / sh i xpg4 / sh) i BSD. Systemy AIX i HP-UX są bardzo zgodne i nie powodują problemów. bash to mały świat.

Polecam ten przewodnik Autoconf przenośny skorupy , która jest absolutnie genialny i oszczędza dużo czasu. Duże fragmenty są przestarzałe, ale to w porządku; po prostu pomiń TruUnix i Ultrix i tak dalej, jeśli cię to nie obchodzi!

Nicholas Wilson
źródło
poshrzeczywiście brzmi jak to, o co proszę. Zrobię testy jak najszybciej.
rahmu
1
Odpowiedziałem, zanim zauważyłem powiązane pytanie! posh jest kwestią debianową, więc nie będzie pakowany w każdym systemie. Ponadto muszla niekoniecznie jest czymś, o co należy się najbardziej martwić; Niezgodności sed są na przykład dużym problemem.
Nicholas Wilson,
Nie zawracałbym sobie głowy przenoszeniem do Solaris / bin / sh, czyli powłoki Bourne'a (która nie jest POSIX). Solaris, jak wszystkie współczesne jednorożce, ma powłokę POSIX, tak się składa, że ​​nie znajduje się w zwykłej lokalizacji (/ usr / xpg4 / bin / sh)
Stéphane Chazelas
Niestety wysyłamy skrypty, które muszą działać przynajmniej na każdym / bin / sh. Nie jest tak źle jak wszystko ... Wolałbym jednak tego nie robić.
Nicholas Wilson,
2
Powodem, dla którego traktuję / bin / sh jako ważne, jest to, że jest wywoływany z shebang w wielu skryptach. „/ usr / bin / env sh” nie jest poprawą. Jeśli zamierzasz włożyć jakiś wysiłek, aby coś działało na powłokach innych niż POSIX, myślę, że równie dobrze mogę nadać priorytet każdemu systemowi / bin / sh. Nie potrwa długo, zanim jakiś klient uruchomi skrypt z domyślną powłoką, co nie jest wcale takie nierozsądne.
Nicholas Wilson,
28

Możesz użyć ShellCheck (GitHub) jako linijki dla swoich skryptów powłoki. Istnieje również wersja online .

Aby wykryć problemy ze zgodnością POSIX (np. SC2039 ), linia shebang skryptu powłoki powinna być #!/bin/sh. Możesz także przejść --shell=shdo shellcheck.

Przykład ( test.sh):

#!/bin/sh
if [[ $HOSTNAME == test ]]; then
    echo fail &> foo
fi

Wynik ( shellcheck test.sh):

In test.sh line 2:
if [[ $HOSTNAME == test ]]; then
   ^-- SC2039: In POSIX sh, [[ ]] is undefined.
      ^-- SC2039: In POSIX sh, HOSTNAME is undefined.    

In test.sh line 3:
    echo fail &> foo
              ^-- SC2039: In POSIX sh, &> is undefined.
johnLate
źródło
1
Przez te wszystkie lata i nigdy nie słyszałem o ShellCheck ... dzięki za link!
Ton van den Heuvel
Najlepsze narzędzie w historii! Zwłaszcza posiadanie jego wersji online jest niesamowite, aby szybko sprawdzić fragment kodu!
Mecki
12

Bash będzie działał w trybie zgodnym z POSIX, jeśli POSIXLY_CORRECTustawiona jest zmienna środowiskowa. Z strony podręcznika:

   POSIXLY_CORRECT
          If  this  variable  is  in the environment when bash starts, the
          shell enters posix mode before reading the startup files, as  if
          the  --posix  invocation option had been supplied.  If it is set
          while the shell is running, bash enables posix mode, as  if  the
          command set -o posix had been executed.

Wiele innych narzędzi GNU również będzie honorować POSIXLY_CORRECT, więc jeśli korzystasz z systemu zawierającego głównie narzędzia GNU (np. Większość systemów Linux), to dobry początek, jeśli twoim celem jest zgodność z POSIX.

James Sneeringer
źródło
21
Nawet w trybie POSIX, bash nadal zezwala na niektóre funkcje inne niż POSIX, takie jak [[.
jordanm