Risorse per la programmazione di shell portatili


65

Quali risorse esistono per la programmazione della shell portatile? La risposta definitiva è testare su tutte le piattaforme target, ma raramente è pratico.

La specifica POSIX / Single UNIX è un inizio, ma non ti dice né quale sia il livello di supporto di ogni implementazione, né quali estensioni comuni esistono. Puoi leggere la documentazione di ogni implementazione, ma è molto dispendiosa in termini di tempo e non completamente accurata.

Mi sembra che un formato ideale sarebbe una sorta di versione annotata dalla comunità delle specifiche POSIX, in cui ogni funzione è annotata dal suo livello di supporto tra le diverse implementazioni. C'è una cosa del genere? O ci sono altre risorse utili?

Ad esempio, ci sono le pagine sulla portabilità della shell di Sven Mascheck , ma si tratta solo di elementi sintattici e di alcuni built-in, e copre solo vecchie shell. Sto cercando una risorsa più completa.


2
NB Non rispondere qui solo per citare un documento di conformità di un'implementazione particolare. Se ne hai uno, il tag wiki corrispondente sarebbe un buon posto.
Gilles 'SO- smetti di essere malvagio' il

1
Qualcuno deve estrarre la cronologia delle revisioni per autoconfe Metaconfig(Perl, rn) e raccogliere tutti i trucchi e i loro commenti esplicativi in ​​un unico posto.
Geekosaur,

@geekosaur: buon suggerimento. Non ho mai visto gli interni di autoconf, c'è qualcosa che si potrebbe usare come guida quando si scrivono i propri script? In tal caso, questa sarebbe una buona risposta alla mia domanda, anche se non è definitiva.
Gilles 'SO-smetti di essere malvagio' il

5
Sono sicuro che entrambi l'avresti trovato facilmente, ma a beneficio di altre persone che stanno seguendo questa discussione, ecco un link a una pagina pertinente dal manuale di autoconf: gnu.org/software/hello/manual/autoconf/Portable- Shell.html
J. Taylor,

Risposte:


32

Il manuale di autoconf ha una sezione sulla programmazione della shell portatile .

Sebbene non sia specificamente destinato a POSIX, è probabilmente la raccolta più completa di cosa fare e non fare quando si tenta di scrivere codice shell portatile.


3
Questa è una delle migliori risorse ed è stata costruita durante la scrittura di codice in M4 che doveva produrre un codice shell che fosse portatile su quante più shell possibili.
Tim Post

6

Oltre a dashe posh, c'è bournesh(o bsh), Heirloom Bourne Shell , che può essere usato per rilevare i Bashismi .

Il progetto Heirloom include anche "The Heirloom Toolchest", una raccolta di oltre 100 utility Unix standard (che potrebbero servire come punto di partenza per confrontare le opzioni della riga di comando).


2
Nota che la shell Bourne non è una shell POSIX, rendere il tuo script portabile alla shell Bourne significherebbe declassare la sintassi dello script dal linguaggio sh POSIX standard al comune denominatore tra quello e la sintassi della shell Bourne. Non vale l'opinione a meno che tu non voglia essere portatile con sistemi antichi (o Solaris 10 e precedenti e non hai la scelta di usare lo sh standard che era in / usr / xpg4 / bin lì).
Stéphane Chazelas,

5

Simile a questa risposta , prova a eseguire il tuo script in posh .

Inoltre, non dimenticare di impostare la POSIXLY_CORRECTvariabile di ambiente su true, poiché questo fa sì che molti programmi (non solo la shell) aderiscano più strettamente agli standard POSIX.


4

Scrivere i tuoi script usando dash potrebbe essere un inizio.


3
Il test con trattino è il minimo indispensabile per evitare la dipendenza accidentale dalle funzionalità di ksh / bash, ma sto cercando di più: conoscere le carenze in altre shell (ad esempio la cattiva gestione delle trap di zsh), e soprattutto nelle utility di shell (ad esempio OpenBSD è findancora non ha implementato -exec +).
Gilles 'SO- smetti di essere malvagio' il

FWIW, OpenBSD findfa al -exec utility {} +giorno d'oggi.
Kusalananda

2

In una certa misura, puoi provare checkbashismsnel devscriptspacchetto Debian / Ubuntu .

Non è perfetto, ma ha il vantaggio di essere un punto di partenza esistente. Ad esempio, non vede le anomalie classiche con sed/ findriguardanti GNU vs BSD / altre differenze.

Per impostazione predefinita, è Debian + dash dash, la -pbandiera può essere utile nel tuo caso.


2

Oggi, di solito è possibile trovare una shell POSIX su un sistema, e ciò significa generalmente che è possibile eseguire lo script nel linguaggio POSIX (modulo in esecuzione in bug di conformità).

L'unico problema è che a /bin/shvolte non è una shell POSIX. E devi codificare la #!linea in script che devono comportarsi come un buon eseguibile; non puoi semplicemente chiedere all'utente di ricercare il problema e quindi invocare il tuo script come /path/to/posix/shell myscript.

Quindi, il trucco è usare le funzionalità POSIX nel tuo script, ma fare in modo che lo script trovi automaticamente la shell POSIX. Un modo per farlo è così:

#!/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.

Esistono altri approcci, come la generazione di codice. Boostrap i tuoi script con un piccolo script che prende un corpo di file di script senza un #! linea e ne aggiunge uno.

La cosa peggiore che puoi fare è iniziare a scrivere interi script in modo tale che vengano eseguiti su una shell Bourne dal 1981. Questo è necessario solo se devi scrivere per un sistema che in realtà non ha altre shell .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.