#! / bin / sh vs #! / bin / bash for maksimal portabilitet

cherouvim 09/07/2017. 3 answers, 2.834 views
linux bash shell sh

Jeg arbejder normalt med Ubuntu LTS-servere, som fra hvad jeg forstår symlink /bin/sh til /bin/dash . En masse andre distros selvom symlink /bin/sh til /bin/bash .

Derefter forstår jeg, at hvis et script bruger #!/bin/sh på toppen, kan det ikke løbe på samme måde på alle servere?

Er der en anbefalet praksis, hvorpå skal skal bruges til scripts, når man ønsker maksimal overførbarhed af disse scripts mellem servere?

1 Comments
Thorbjørn Ravn Andersen 08/01/2017
Der er små forskelle mellem de forskellige skaller. Hvis portabilitet er det vigtigste for dig, skal du bruge #!/bin/sh og ikke bruge noget andet end hvad den originale skal leverede.

3 Answers


Gordon Davisson 08/01/2017.

Der er omkring fire niveauer af bærbarhed til shell-scripts (hvad angår shebang-linjen):

  1. Mest bærbare: Brug en #!/bin/sh shebang og brug only den grundlæggende shell syntaks, der er specificeret i POSIX standarden . Dette skal fungere på stort set alle POSIX / unix / linux-systemer. (Tja, undtagen Solaris 10 og tidligere, der havde den ægte gamle Bourne-shell, forud for POSIX så ikke-kompatibel, som /bin/sh .)

  2. Anden mest bærbare: Brug en #!/bin/bash (eller #!/usr/bin/env bash ) shebang linje, og hold dig til bash v3-funktioner. Dette vil fungere på ethvert system, der har bash (på det forventede sted).

  3. Tredje mest bærbare: Brug en #!/bin/bash (eller #!/usr/bin/env bash ) shebang linje, og brug bash v4 funktioner. Dette vil mislykkes på ethvert system, der har bash v3 (f.eks. MacOS, som skal bruge det til licensårsager).

  4. Mindst bærbare: Brug en #!/bin/sh shebang og brug bash extensions til POSIX shell syntaks. Dette vil mislykkes på ethvert system, der har noget andet end bash for / bin / sh (såsom nyere Ubuntu versioner). Gør aldrig det her; det er ikke bare et kompatibilitetsproblem, det er bare ret forkert. Desværre er det en fejl, mange mennesker laver.

Min anbefaling: Brug de mest konservative af de første tre, der leverer alle de shell-funktioner, du har brug for til scriptet. For maksimal portabilitet, brug valg nr. 1, men i min erfaring er nogle bash-funktioner (som arrayer) tilstrækkelige nok til at jeg går med # 2.

Det værste du kan gøre er # 4, ved at bruge den forkerte shebang. Hvis du ikke er sikker på, hvilke funktioner der er basale POSIX, og som er bash-udvidelser, skal du holde fast i en bash shebang (dvs. valg nr. 2), eller test scriptet grundigt med en meget grundlæggende shell (som dash på dine Ubuntu LTS-servere). Ubuntu wiki har en god liste over bashisms at passe på .

Der er nogle meget gode oplysninger om historien og forskellene mellem skaller i Unix & Linux spørgsmålet "Hvad betyder det at være kompatibelt med Sh?" og Stackoverflow-spørgsmålet "Forskel mellem sh og bash" .

Vær også opmærksom på, at skallen ikke er den eneste, der adskiller sig mellem forskellige systemer; Hvis du er vant til Linux, er du vant til GNU-kommandoerne, som har mange ikke-standardudvidelser, du måske ikke finder på andre unix-systemer (f.eks. bsd, macOS). Desværre er der ingen simpel regel her, du skal bare kende variationsområdet for de kommandoer, du bruger.

En af de nastiest kommandoer i form af bærbarhed er en af ​​de mest grundlæggende: echo . Hver gang du bruger det med valgmuligheder (f.eks. echo -n eller echo -e ) eller med undslippe (tilbageslag) i den streng, der skal udskrives, vil forskellige versioner gøre forskellige ting. Når du vil udskrive en streng uden en linefeed efter den, eller med undslippe i strengen, skal du bruge printf stedet (og lære hvordan det virker - det er mere kompliceret end echo er). ps kommandoen er også et rod .

En anden generel ting-at-se-for er nylige / GNUish-udvidelser til kommandobeskrivelsessyntax: gamle (standard) kommandotilstand er, at kommandoen efterfølges af muligheder (med et enkelt punktum, og hver valgmulighed er et enkelt bogstav) efterfulgt af kommando argumenter. Nylige (og ofte ikke-bærbare) varianter omfatter lange muligheder (normalt introduceret med -- ), hvilket giver mulighed for at komme efter argumenter og bruge -- at adskille indstillinger fra argumenter.

5 comments
12 pabouk 07/30/2017
Den fjerde mulighed er simpelthen en forkert ide. Brug venligst det ikke.
3 Gordon Davisson 07/30/2017
@pabouk Jeg er helt enig, så jeg redigerede mit svar for at gøre det klart.
1 jlliagre 07/30/2017
Din første erklæring er lidt vildledende. POSIX-standarden angiver ikke noget om shebang uden at fortælle at bruge det, fører til uspecificeret adfærd. Desuden angiver POSIX ikke, hvor posix skalen skal være placeret, kun dens navn ( sh ), så /bin/sh er ikke garanteret at være den rigtige vej. Den mest bærbare er så ikke at angive nogen shebang overhovedet, eller at tilpasse shebang til det anvendte OS.
2 Michael Kjörling 07/30/2017
Jeg faldt for nylig i # 4 med et script af mig, og kunne bare ikke finde ud af, hvorfor det ikke fungerede; De samme kommandoer fungerede trofast og gjorde præcis det, jeg ville have dem at gøre, da jeg prøvede dem direkte i skallen. Så snart jeg skiftede #!/bin/sh til #!/bin/bash , fungerede scriptet perfekt. (Til mit forsvar havde dette script udviklet sig over tid fra en, der virkelig kun havde brug for sh-isms, til en, der stolte på bash-lignende adfærd.)
2 jlliagre 07/30/2017
@ MichaelKjörling Den (ægte) Bourne-shell er næsten aldrig bundtet med Linux-distributioner og er alligevel ikke POSIX-kompatibel. POSIX-standardskallen blev oprettet fra ksh opførsel, ikke Bourne. Hvad de fleste Linux-distributioner efter FHS gør, er at have /bin/sh er et symbolsk link til den shell, de vælger at levere POSIX-kompatibilitet, normalt bash eller dash .

Kaz 07/31/2017.

I ./configure scriptet, som forbereder TXR-sproget til bygning, skrev jeg følgende prolog for bedre overførbarhed. Scriptet starter op, selvom #!/bin/sh er et Bourne Shell, der ikke er POSIX-kompatibelt. (Jeg bygger hver udgivelse på en Solaris 10 VM).

#!/bin/sh

# use your own variable name instead of txr_shell;
# adjust to taste: search for your favorite shells

if test x$txr_shell = x ; then
  for shell in /bin/bash /usr/bin/bash /usr/xpg4/bin/sh ; do
    if test -x $shell ; then
       txr_shell=$shell
       break
    fi
  done
  if test x$txr_shell = x ; then
    echo "No known POSIX shell found: falling back on /bin/sh, which may not work"
    txr_shell=/bin/sh
  fi
  export txr_shell
  exec $txr_shell $0 ${@+"$@"}
fi

# rest of the script here, executing in upgraded shell 

Ideen her er, at vi finder en bedre skal end den, vi kører under, og genudfør scriptet ved hjælp af denne shell. txr_shell miljøvariablen er indstillet, så det genudførte script ved, at det er den genudførte rekursive forekomst.

(I mit script bruges txr_shell variablen også til præcis to formål: For det første udskrives den som en del af en informativ meddelelse i scriptets output. For det andet installeres den som SHELL variablen i Makefile , således at make vil bruge denne shell også til at udføre opskrifter.)

På et system hvor /bin/sh er dash, kan du se, at ovenstående logik finder /bin/bash og genudfør scriptet med det.

I en Solaris 10-boks vil /usr/xpg4/bin/sh sparke ind, hvis der ikke findes Bash.

Proloven er skrevet i en konservativ skaldialekt, ved hjælp af test for fileksistensprøver og ${@+"$@"} tricket for at udvide argumenter, der passer til nogle ødelagte gamle skaller (som simpelthen ville være "$@" hvis vi var i en POSIX-konformerende skal).

2 comments
Charles Duffy 07/31/2017
Man ville ikke have brug for x hackeryet, hvis korrekt citering var i brug, da de situationer, der pålagde dette idiom, omgiver nu-afprøvede testindkaldelser med -a eller -o kombinere flere tests.
Kaz 07/31/2017
@CharlesDuffy Faktisk; test x$whatever hvad jeg begår der ligner et løg i lakken. Hvis vi ikke kan stole på den ødelagte gamle shell, der skal citere, er det endelige ${@+"$@"} forsøg meningsløst.

zwol 07/31/2017.

Alle variationer af Bourne shell-sproget er objektivt forfærdelige i forhold til moderne skriptsprog som Perl, Python, Ruby, node.js og endog (muligvis) Tcl. Hvis du skal gøre noget endda lidt kompliceret, vil du være gladere i det lange løb, hvis du bruger et af ovenstående i stedet for et shell script.

Den eneste fordel, som skalssproget stadig har over de nyere sprog, er at something kalder sig selv /bin/sh er garanteret at eksistere på noget, der påstår at være Unix. Det kan dog ikke engang være POSIX-kompatibelt; mange af de gamle proprietære Unixes frøs det sprog, der blev implementeret af /bin/sh og værktøjerne i standard PATH prior ændringerne krævet af Unix95 (ja, Unix95, tyve år siden og tæller). Der kan være et sæt Unix95 eller endda POSIX.1-2001 hvis du er heldig, værktøjer i en mappe not på standard PATH (f.eks. /usr/xpg4/bin ), men de garanteres ikke at eksistere.

Grundlæggende om Perl er dog more likely til at være til stede på en vilkårligt valgt Unix-installation, end Bash er. (Ved "Grundlæggende om Perl" mener jeg /usr/bin/perl og er some , muligvis ret gamle, version af Perl 5, og hvis du er heldig er det sæt af moduler, der leveres med den pågældende version af tolken, også ledig.)

Derfor:

Hvis du skriver noget, der skal arbejde everywhere der angiveligt er Unix (som et "configure" script), skal du bruge #! /bin/sh #! /bin/sh , og du behøver ikke bruge nogen udvidelser overhovedet. I dag ville jeg skrive POSIX.1-2001-kompatibel skal under disse omstændigheder, men jeg ville være parat til at patchere ud POSIXisms, hvis nogen bad om støtte til rustfrit jern.

Men hvis du not skriver noget, der skal arbejde overalt, så er det i det øjeblik, du er fristet til at bruge nogen Bashisme overhovedet, du skal stoppe og omskrive hele sagen i et bedre script sprog i stedet. Din fremtidige selv vil takke dig.

(Så hvornår is det hensigtsmæssigt at bruge Bash-udvidelser? Til førstegangsordre: Aldrig. For anden rækkefølge: Kun for at udvide det interaktive Bash-miljø - f.eks. For at give smart tabulering og fancy beskeder.)


HighResolutionMusic.com - Download Hi-Res Songs

1 The Chainsmokers

Beach House flac

The Chainsmokers. 2018. Writer: Andrew Taggart.
2 (G)I-DLE

POP/STARS flac

(G)I-DLE. 2018. Writer: Riot Music Team;Harloe.
3 Anne-Marie

Rewrite The Stars flac

Anne-Marie. 2018. Writer: Benj Pasek;Justin Paul.
4 Ariana Grande

​Thank U, Next flac

Ariana Grande. 2018. Writer: Crazy Mike;Scootie;Victoria Monét;Tayla Parx;TBHits;Ariana Grande.
5 Clean Bandit

Baby flac

Clean Bandit. 2018. Writer: Jack Patterson;Kamille;Jason Evigan;Matthew Knott;Marina;Luis Fonsi.
6 BTS

Waste It On Me flac

BTS. 2018. Writer: Steve Aoki;Jeff Halavacs;Ryan Ogren;Michael Gazzo;Nate Cyphert;Sean Foreman;RM.
7 Imagine Dragons

Bad Liar flac

Imagine Dragons. 2018. Writer: Jorgen Odegard;Daniel Platzman;Ben McKee;Wayne Sermon;Aja Volkman;Dan Reynolds.
8 Nicki Minaj

No Candle No Light flac

Nicki Minaj. 2018. Writer: Denisia “Blu June” Andrews;Kathryn Ostenberg;Brittany "Chi" Coney;Brian Lee;TJ Routon;Tushar Apte;ZAYN;Nicki Minaj.
9 Brooks

Limbo flac

Brooks. 2018.
10 BlackPink

Kiss And Make Up flac

BlackPink. 2018. Writer: Soke;Kny Factory;Billboard;Chelcee Grimes;Teddy Park;Marc Vincent;Dua Lipa.
11 Diplo

Close To Me flac

Diplo. 2018. Writer: Ellie Goulding;Savan Kotecha;Peter Svensson;Ilya;Swae Lee;Diplo.
12 Rita Ora

Velvet Rope flac

Rita Ora. 2018.
13 Fitz And The Tantrums

HandClap flac

Fitz And The Tantrums. 2017. Writer: Fitz And The Tantrums;Eric Frederic;Sam Hollander.
14 Little Mix

Woman Like Me flac

Little Mix. 2018. Writer: Nicki Minaj;Steve Mac;Ed Sheeran;Jess Glynne.
15 Billie Eilish

When The Party's Over flac

Billie Eilish. 2018. Writer: Billie Eilish;FINNEAS.
16 K-391

Mystery flac

K-391. 2018.
17 Cher Lloyd

None Of My Business flac

Cher Lloyd. 2018. Writer: ​iamBADDLUCK;Alexsej Vlasenko;Kate Morgan;Henrik Meinke;Jonas Kalisch;Jeremy Chacon.
18 Backstreet Boys

Chances flac

Backstreet Boys. 2018.
19 Lil Pump

Arms Around You flac

Lil Pump. 2018. Writer: Rio Santana;Lil Pump;Edgar Barrera;Mally Mall;Jon Fx;Skrillex;Maluma;Swae Lee;XXXTENTACION.
20 Kelly Clarkson

Never Enough flac

Kelly Clarkson. 2018. Writer: Benj Pasek;Justin Paul.

Related questions

Hot questions

Language

Popular Tags