The UNIX and Linux Forums  


Go Back   UNIX och Linux Forum > Upp Forum > UNIX for Dummies Frågor & Svar > Svar på vanliga frågor > Tips och Tutorials
.
google unix.com



Tips och Tutorials Nyttiga artiklar från våra användare.

Mer UNIX och Linux Forum Ämnen Du kan hitta Helpful
Tråd Thread Starter Forum Svar Senaste Inlägg
Learning Oracle ADF: A beginner's Story iBot Oracle Uppdateringar (RSS) 0 04-06-2008 06:10
CEP och historien om Fisk iBot Complex Event Processing RSS Nyheter 0 12-17-2007 05:50
Bangkok Post Artikel: Historien bakom Linux operativsystem Neo Nyheter, länkar, evenemang och Tillkännagivanden 0 04-05-2003 10:05

 
English Japanese Spanish French German Portuguese Italian Dutch Swedish Russian Norwegian Hungarian Hebrew Danish Bulgarian Greek Powered by Powered by Google
 
LinkBack Thread Tools Sök i denna tråd Rate Thread Visningslägen
  #1 (permalänk)  
Old 03-31-2007
Perderabo's Avatar
Perderabo Perderabo is offline Forum Staff  
Unix Daemon
  
 

Join Date: Aug 2001
Ort: Ashburn, Virginia
Inlägg: 9.126
Hela historien på #! / usr / bin / ksh

Inledning

Ursprungligen vi bara hade ett skal på Unix. När sprang ett kommando skalet skulle försöka att åberopa en av exec () innebär att man på det. Det kommandot en körbar, den exec skulle lyckas och kommandot körs. Om exec () misslyckades, tanken skulle inte ge upp, i stället skulle försöka tolka kommandot fil som om den vore ett shell script. Detta fungerar bra så länge finns det bara ett skal i systemet. Men om du använder ett skal som din interaktiva och vill köra ett script skrivet i ett annat skal språk?

Det är här #! trick kommer in idén att använda # företräda en kommentar grundar csh och snabbt läggas till Bourne-skal. Nu tankskal vet att ignorera saker efter ett #. Så vi kan lägga till en ledande online något i stil med "#! / Usr / bin / ksh. Så tanken här är bara en kommentar. Men om kärnan försöker köra en fil med denna linje kommer det att exec angiven tolk och låt manus till den. Så skalskript blivit körbar ganska likt riktiga exekverbara filer är. Nu när ett skal försöker exec ett shell script, det lyckas.

Vad händer om du lämnar bort #! linje? Tja, kärnan exec att misslyckas. Din genomsnittliga skal kommer sedan försöker köra scriptet själv. Några tankar att försöka inspektera script för att försöka gissa språket. Detta är inte bra. Du kan köra ksh som din interaktiva skal och skriva ksh skript. Om du senare byta till bash som ett interaktivt skal, några av dina skript kan fortsätta att köra medan andra misslyckas. Även linje är en kommentar som ger en viktig ledtråd till en programmerare som tittar på skript för att förstå det. Att veta vilket språk författaren försöker använda är en stor hjälp.

Samtidigt som jag har använt termen "skal", som faktiskt har den här tekniken kan användas med många program som inte skal. Här är ett "script" för att visa en multiline meddelande:
Kod:
#! /usr/bin/cat
Line 1
Line 2 
Line 3

Det här kommer att visa att "#! / Usr / bin / cat", men förutom att det fungerar ganska bra.

Skicka ett argument

Du kan skicka en enda argumentet så här:
#! / usr / local / bin /perl -w
Men i allmänhet är du begränsad till en argument. På de flesta system, en rad som denna: "#! / Del / tolk-ett-b" resulterar i "-a-b" som gått som ett enda argument. Det enda argument är inte begränsad till att börja med ett bindestreck. Vi kan förbättra vårt budskap script:
Kod:
#! /usr/bin/sed 1d
Line 1
Line 2 
Line 3

Exempel

Låt oss sätta allt detta tillsammans med ett exempel. Här är en perl skript som jag kommer att kalla perlargs:
Kod:
#! /usr/local/bin/perl -w

#! /usr/local/bin/perl -w
print "script name is ", $0, "\n";
while (@ARGV) {
        $ARGV = shift @ARGV;
        print "argument ", $i++,  " is ", $ARGV, "\n";
}

system "ps -f -ww";


De-w frågar perl Frågan varningsmeddelanden. Skriptet bara visar sina argument och sedan kör ps kommandot. När jag kör det får jag:
Kod:
$ ./perlargs one two three
Name "main::i" used only once: possible typo at ./perlargs line 10.
script name is ./perlargs
argument 0 is one
argument 1 is two
argument 2 is three
                 UID        PID   PPID    STIME TTY     TIME CMD
                 perderabo   69      1 17:47:28 n01  0:00.24 /bin/ksh -l
                 perderabo  201     69 18:28:22 n01  0:00.03 /usr/local/bin/perl -w ./perlargs one two three
                 perderabo 2055    201 18:28:22 n01  0:00.01 ps -f -ww
$

Observera att perl Processen kallades med 5 argument. Den 2:a argument är namnet på skriptet. Det är upp till perl process för att lägga fram de 3 sista argument argumentet listan framgår av skriptet. Dessutom inser kärnan startat perl process. Därefter är det upp till perl att öppna manus och läsa den och kör varje rad. Därför skript måste vara läsbar. Du kan inte köra en icke läsbar stil.

Slutsats

Detta bör vara tillräckligt med information för att förstå vad som händer med dem #! linjer. I följande inlägg kommer jag att lägga till information om olika aspekter av processen.
  #2 (permalänk)  
Old 03-31-2007
Perderabo's Avatar
Perderabo Perderabo is offline Forum Staff  
Unix Daemon
  
 

Join Date: Aug 2001
Ort: Ashburn, Virginia
Inlägg: 9.126
Del 2 - Detaljer

Formatet på #! Line

Vi kan säga med säkerhet att de första 2 tecken måste "#!". Eller kan vi? Många system, verkar det som, är villiga att ta bort ledande blanktecken. Min rekommendation är att börja med #!. Det traditionella.

Nästa det kan vara en valfri plats. Vissa handlingar säger att detta utrymme behövs, men så långt som vem som helst kan bestämma bara Unix release att kräva utrymmet var en ögonblicksbild utsättning av BSD 4.1 ... detta inte var en allmän utsättning). Faktiskt verkar det som du kan ha flera platser om du vill. Och en del tester med TAB tecken har gjort och verkar fungera. Min rekommendation är att följa med noll eller ett mellanslag.

Därefter kommer den fullständiga sökvägen till tolk och som alla fullständiga sökvägar måste det börja med ett /. Oj, ett annat undantag ... Linux-kärnan (minst version 2.0.34) är beredd att acceptera en relativ sökväg. Min rekommendation är inte gör det.

Vi kan göra. Eller vi kan ha valfritt blanktecken som leder till vår enda argument. Förutom att vissa versioner av FreeBSD hantera flera argument.

De flesta versioner av BSD och HP-UX kommer band avslutande blanktecken. Andra versioner av Unix behandla avslutande blanktecken som giltiga tecken. Och ett par versioner av BSD kan godta en avslutande kommentar avgränsas av ett # tecken.

Hur länge kan linjen bli? Några versioner av Unix anger gränsen så låg som 32 tecken. FreeBSD tydligen kan hantera 8192 tecken.

Minst linjen alltid slutar med Unix standard \ n tecken, eller hur? Tja, inte alltid. Vissa versioner av Unix kommer att tolerera ett \ r \ n slutar och band utanför \ r medan andra inte kommer att göra det.

Detta är inte som standard eftersom det kan vara ...

Argument 0 av processen, inte Script

Det finns ett annat sätt att genomförandet kan variera. Tänk perl skript som sprang jag ar i slutet av del 1. Mitt skal gjorde den ungefärliga motsvarighet till
execl ( ". / perlargs" ". / perlargs", "En", "två", "tre", (char *) NULL)
och kärnan omvandlas det till den ungefärliga motsvarigheten till
execl ( "/ usr / local / bin /perl" "/ usr / local / bin /perl", "-W", ". / Perlargs", "en", "två", "tre", (char *) NULL)

Markerat i rött är argumentet noll som konventionellt är densamma som den väg av programmet genomförs. En anmärkningsvärd utförandet är att logga in programmet kommer att ställa det till saker som "-ksh. Ursprungligen körbara skalskript hade argumentet 0 inställt på namnet på skriptet i stället namnet på tolk. Dessa dagar, namnet på den tolk är gemensamma. Den sista håll ut jag känner till är HP-UX där argumentet 0 till namnet på skriptet.
  #3 (permalänk)  
Old 04-01-2007
Perderabo's Avatar
Perderabo Perderabo is offline Forum Staff  
Unix Daemon
  
 

Join Date: Aug 2001
Ort: Ashburn, Virginia
Inlägg: 9.126
Del 3 - SUID Shell Scripts

När körbara skalskript först infördes de hedrad av suid bit. Detta var en katastrof för säkerheten. Fundera ett skriptanrop / usr / sbin / katastrof. Och vi gjorde:
chown root / usr / sbin / katastrof
chmod 4755 / usr / sbin / katastrof
Naturligtvis, /, / usr, / usr / sbin endast skrivbara av root. Och manuset är i sig bara:
#! / bin / sh
Det stämmer. Skriptet är en enda rad utan dolda tecken. Skalet kommer att ignorera det eftersom det är en kommentar och sedan stänga eftersom det inte finns några andra linjer. Detta skript är redan osäker och är utsatta för två olika attacker.

Attack 1: länk till-i

Om vi gör:
ln-s / usr / sbin / katastrof. /-i
och låta verkställa vår nya symbolisk länk kallad "-i". Om vi verkställa de verkliga / usr / sbin / katastrof, vi gör motsvarande:
execl ( "/ bin / sh", "/ usr / sbin / katastrof", "/ usr / sbin / katastrof", (char *) NULL)
Inga problem där. Det är vad vi väntat. Men när vi kör kopia särskild länk kallad "-i" vi gör:
execl ( "/ bin / sh", "-i", "-i", (char *) NULL)
Detta orsakar suid tanken att fungera som ett interaktivt skal! Skalet var snabbt modifieras för att acceptera ett enda bindestreck som i slutet av växlar inställningen argument. Så vi ändrar vår en linje script för att läsa:
#! / bin / sh --
Nu samma trick skulle resultera i:
execl ( "/ bin / sh", "-i", "-", "-i", (char *) NULL)
Augument noll är fortfarande "-i", men detta är ofarligt. Det kan även vara användbara eftersom det gör denna attack mer märkbar med ps kommandot.

Attack 2: Ändra länk

Detta är svårare att förklara. Liksom tidigare kommer vi göra en symbolisk länk till skriptet under attack, men den här gången namnet spelar ingen roll. Då kommer vi köra skriptet via vår nya symbolisk länk. Då vi snabbt ändra den symboliska länken för att peka till en ond script. Vi vill ändra vad den symboliska länken pekar på efter kärnan öppnar det men innan tolk öppnar det. Detta är en ras villkor och det kommer inte att fungera varje gång. Det kräver också lite smart planering att dra detta ett av. Men gjort rätt, kommer vi att ha vår onda skript körs som root.

Suid Skript Inaktiverad

Eftersom det inte var möjligt att skriva en säker suid shell script, begreppet suid skalskript togs bort från Unix. Runt denna Temne programmet sudo skrevs och detta till stor del oviated behovet av suid skalskript. Jag tror inte någon version av Unix släppts under de senaste 15 åren har dessa problem. (Och om jag gjorde skulle jag inte ha diskuterat dessa attacker. ) Nu hoppas jag att ni kan förstå varför många gamla Temne system admins (som jag själv) har fortfarande en svag bild av suid skalskript.

Återlämnandet av Suid Skript

Solaris stöder nu suid skalskript men är immuna mot dessa attacker. Det gör detta genom att se till att scriptet öppnas bara en gång vid en suid script. Om suid biten har angetts, Solaris använder fd filsystem kommer att gå igenom manus till tolk. Hade min perlargs script varit suid på Solaris, skulle det ha körts något liknande:
execl ( "/ usr / local / bin /perl"," / Usr / local / bin /perl","-W "," / dev/fd/3 "," en "," två "," tre ", (char *) NULL)
och när perl öppnas / dev/fd/3, det blir bara en annan öppen fil descripter pekar i samma fil som oberoende har öppnats som FD 3. Observera att i manus, det finns inget sätt att få namnet annat än / dev/fd/3.

Eftersom det namn som används är dold från intrepreter, finns det ingen skada om det namnet var något konstigt som "-i". Eftersom skriptet öppnas en tid finns det ingen skada om en symbolisk länk plötsligt bytt till en ond script.

Men observera att detta äntligen får vi ett stadium där en en linje manus innehåller bara en kommentar kan säkert köra. Det kan fortfarande finnas andra problem med en dåligt skriven suid script. Om du måste använda suid shell scripts, här är några tips:

1. Använd ksh
Dave Korn analyseras alla de attacker mot skalskript och stängas så många hål som han kunde. I synnerhet ksh är immuna mot IFS baserade attacker. Även om den finner att det kommer en interaktiv med en effektiv uid i roten tillsammans med en verklig uid som inte root, det kommer att använda sin rot myndigheten att fastställa det faktiska uid till de verkliga uid före utfärdar en prompt.

2. Control PATH
Uttryckligen ange din PATH variabel som ett första steg i ditt manus. Gör kataloglistan så kort som möjligt. Får inte börja eller avsluta listan med ett kolon eller har två kolon. Och du behöver inte sätta. eller .. i listan. Uttryckligen export PATH. Och se till att varje katalog i PATH är skrivbar bara av root. Till exempel / usr / local / bin är på vägen, utöver det uppenbara behovet av / usr / local / bin som inte är skrivbar, du måste också se till att /, / usr, / usr / local är alla inte skrivbar. Om / usr / local är monterade filsystem, det får inte vara möjligt för en icke-root-användare att se till att / usr / local vara omonterade. Du kan ytterligare skydda dina manus med hjälp av PATH så lite som möjligt. Så till exempel använda "/ usr / bin / rm" snarare än bara "rm".

Obs: jag / usr / local / bin som ett exempel skulle jag starkt motsätter sig att lägga / usr / local / bin i vägen för en suid script. Återigen: göra kataloglistan så kort som möjligt. Jag vill sällan gå längre än "PATH \u003d / usr / bin" i en suid script.

3. Control IFS
Ställ IFS till ett utrymme, en flik och en newline. Och sedan exportera IFS. Även ksh är immun mot den IFS attack, några andra tankar inte är immuna. Något du gör i ditt manus indirekt kan åberopa en annan skal.

4. Se till att skriptet kan inte skriva
De flesta versioner av Unix dessa dagar kommer att ta bort suid bit på en fil som den är skriven av en process som ägs av en användare annat än ägaren av filen. Men inte är beroende av att beteendet.

5. Försök inte utföra direkt eller indirekt alla användare levereras ingång
Du måste se till att användardata aldrig levererats till tanken att tolka som exekverbar kod. Om du inte vet hur man skall se detta, så ska du inte behandla alla användardata. Observera att de parametrar som skriptet måste betraktas användardata.

6. Var försiktig om du åberopa program att begära in synpunkter från användarna
Inte åberopa program som låter användaren köra godtyckliga program. Till exempel, inte uppmana användaren att VI en fil. VI erbjuder ett sätt för användaren att utföra en subshell. Ja, ksh inbyggda skydd skyddar dig om användaren åberopar ksh interaktivt. Men tyvärr, andra tankar finns. Och användaren behöver inte ett interaktivt skal med VI. Ett kommando som ":! Rm / etc / passwd" kommer att arbeta från VI och detta är inte med hjälp av en interaktiv skal.

Dessa steg kommer att gå en lång väg mot att säkra en suid skript du skriver, men jag kan inte garantera att de är tillräckligt för att helt säkert ett manus.
  #4 (permalänk)  
Old 04-01-2007
Perderabo's Avatar
Perderabo Perderabo is offline Forum Staff  
Unix Daemon
  
 

Join Date: Aug 2001
Ort: Ashburn, Virginia
Inlägg: 9.126
Del 4: GREJER

Uppfanns av Dennis Ritchie

Begreppet har sitt ursprung med Dennis Ritchie:
Kod:
>From dmr Thu Jan 10 04:25:49 1980 remote from research
The system has been changed so that if a file being executed
begins with the magic characters #! , the rest of the line is understood
to be the name of an interpreter for the executed file.
Previously (and in fact still) the shell did much of this job;
it automatically executed itself on a text file with executable mode
when the text file's name was typed as a command.
Putting the facility into the system gives the following
benefits.

1) It makes shell scripts more like real executable files,
because they can be the subject of 'exec.'

2) If you do a 'ps' while such a command is running, its real
name appears instead of 'sh'.
Likewise, accounting is done on the basis of the real name.

3) Shell scripts can be set-user-ID.

4) It is simpler to have alternate shells available;
e.g. if you like the Berkeley csh there is no question about
which shell is to interpret a file.

5) It will allow other interpreters to fit in more smoothly.

To take advantage of this wonderful opportunity,
put

	#! /bin/sh

at the left margin of the first line of your shell scripts.
Blanks after ! are OK.  Use a complete pathname (no search is done).
At the moment the whole line is restricted to 16 characters but
this limit will be raised.


From uucp Thu Jan 10 01:37:49 1980

BSD plockade upp den från version 8 av forskning Unix och har gjort det populärt.

Vad ska Ring Concept

Så småningom, på #! linjen kom att kallas "sharpbang" och sharpbang finns fortfarande i vissa kärnans källkod. Detta förkortas till "RUBBET" på något sätt. Jag hade förväntat "shabang" men det verkar som "RUBBET" är vad de flesta människor använder. Några människor verkar använda "hashpling". Synbarligen, SCO har en switch som heter "hashplingenable" som måste ställas in kärnan bygga tid att aktivera den här funktionen. Och jag har fått höra att en del folk använda termen "hashbang". (Alla för sharppling?)


Särskilda regler för Perl

Det bör påpekas att flera argument på #! linje ofta gått som ett enda argument. Om perl passerar ett argument som "-en-b". det kommer att bryta isär och agera som "en" och "b" hade gått. Även perl inte ignorera #! linje. Perl kommer att granska den och vänder på alla växlar den finner. Detta bidrar kompensera för system med en mycket kort #! linje gräns. perl söker en #! linje tills den hittar den strängen "perl". Därefter startar scanning för switchar. Under denna scan" -* "och" - "ignoreras. Om #! Linje inte innehåller strängen"perl" perl kommer att behandla #! linje hur en Unix-kärna skulle och därmed göra en korrekt tolk.

Hantering av olika vägar

Låt oss säga att vissa system har exempelvis / opt /perl/bin /perl och / usr / local / bin /perl. Hur man skriver en perl script? Min känsla är att det faller på systemadministratören att ge de nödvändiga gemensamma. Jag skulle sätta perl i / usr / local / bin. Om perl installationsproceduren sätter perl i / opt /perl/bin /perlDet är fina ... men då skulle jag en symbolisk länk i / usr / local / bin som pekar på perl körbar. Samma sak med perl. Så om alla system under min kontroll "#! / Usr / local / bin / python" garanteras att arbeta eller python är inte tillgänglig på det systemet. Samma sak med perlEtc. Det är ovanligt för mig att lägga till en länk till en katalog som / usr / bin. Men jag kommer att göra detta för ksh och bash bör en OS saknas antingen skal. Och jag alltid se till att bash och ksh kommer att fungera om saker som / opt och / usr / local är omonterade. Dessa tankar är de enda fall där jag kommer att åsidosätta installationen om jag måste. Så på min system saker som detta kommer att fungera:

#! / usr / bin / ksh
#! / usr / bin / bash
#! / usr / local / bin /perl

Och tills det här fungerar, jag anser inte att OS installation att bli komplett. Skript som importeras från omvärlden kan behöva en tweak för att köra om de förväntar tolkarna annorstädes. Men program som "konfigurera" hittar perl om det ligger i / usr / local / bin. Så det här är min strategi. Men det finns andra idéer ...

En annan metod är att använda en #! linje som leder till ett mellanliggande program som åberopar önskade tolk efter en PATH sökning. De mest använda exempel skulle vara något i stil med "#! / Usr / bin / env perl". Detta förutsätter att env är / usr / bin (inte fallet med exempelvis Unicos, men min ovanstående synpunkter gälla env och jag skulle lägga den nödvändiga länkar). Det förutsätter dessutom att perl är på väg någonstans. Ett mer omfattande exempel är
Kod:
#! /usr/bin/sh -- # -*- perl -*- -p
eval 'exec perl -S $0 ${1+"$@"}'

Och ännu närmare exempel i boken Programmering Perl av Larry Wall, et al.

Och Posix Standard för webbplatsen kontroller med
Citat:
Vidare på system som stödjer körbara skript (det "#!" Konstruera), rekommenderas det att program som använder körbara skript installera dem med getconf-v för att bestämma skal sökvägen och uppdatera "#!" script lämpligt eftersom det är installerat (till exempel med sed).
Se den länkade sidan för deras föreslagna installationsskriptet.

Den ksh utökade miljön

Låt säga att du använder ksh uteslutande och du har ett manus och du lämnar bort "#!". Din interaktiva ksh försöker exec skriptet och misslyckas. Så din interaktiva ksh med falla tillbaka för att köra skriptet som ksh script. Det gör detta genom Forking en kopia av sig själv för att skapa en subshell. Detta kluven subshell kan sedan i själva verket bygger vidare på den standard Unix begreppet "miljö". När en process exec är en annan process, det nya programmet ärver en massa saker, öppna filer, aktuella katalogen och miljö. Miljön är en uppsättning strängar som genom avtal, ges i form av rörlig inställningar, som: PATH \u003d / usr / bin: / usr / local / bin. Men kluven ksh subshell vet allt om den förälder subshell. Tidig ksh version utnyttjade detta genom att ha olika sätt att exportera Arrays, alias och funktioner. Detta kräver att undvika #! linje och därmed lever med de problem som detta skapar. De flesta webbplatser som uppmuntrar användningen av #! linje och detta underminerar ksh utökade miljön begreppet. Och det förvirrade nybörjare som såg saker som exporteras alias nämns i dok. De senaste versionerna av ksh har reträtt från den utökade miljön begreppet. Så mitt förslag är att glömma ksh exporteras Arrays, alias och funktioner och använda #! linje.
 

Komihåglista

Taggar
perl, perl skift, RUBBET, växla, skift perl

Thread Tools Sök i denna tråd
Sök i denna tråd:

Avancerad sökning
Visningslägen Betygsätt denna tråd
Betygsätt denna tråd:

Utstationering Regler
Du får inte efter nya trådar
Du får inte efter svar
Du får inte skicka bilagor
Du får inte redigera dina inlägg

BB-kod är
Smilies är
[IMG] kod
HTML-koden är Av
Trackback är
Pingbacks är
Refbacks är




Alla tider är GMT -4. Klockan är nu 08:39.


Powered by: vBulletin, Copyright © 2000 - 2006, Jelsoft Enterprises Limited. Översättningar Powered by .
vBCredits v1.4 Copyright © 2007 - 2008, PixelFX Studios
UNIX och Linux Forum Innehållet upphovsrättsskyddat © 1993-2009. All Rights Reserved.Ad förvaltning RedTyger

Content Relevant webbadresser från vBSEO 3.2.0