Ha el kell indítanod egy shell scriptet, hogyan teszed?

Címkék

./ennek-kell-futnia.sh
76% (459 szavazat)
sh ./ennek-kell-futnia.sh
7% (40 szavazat)
bash ./ennek-kell-futnia.sh
4% (26 szavazat)
source ./ennek-kell-futnia.sh
0% (2 szavazat)
egyéb módon/attól függ
8% (48 szavazat)
soha nem futtatok shell scripteket
0% (3 szavazat)
Csak az eredmény érdekel.
3% (21 szavazat)
Egyéb, leírom.
1% (5 szavazat)
Összes szavazat: 604

Hozzászólások

Én mindig az elsőt használom, és viszonylag sok scriptet is írok. Most futottam bele, közreadtam egy scriptet, mire kolléga szól, hogy nem jó. Kiderült, hogy ő így futtatja: "sh ./ennek-kell-futnia.sh" a scriptben persze voltak nem kompatibilis dolgok.... Most rakhatok bele ellenőrzést, hogy biztos bash van-e alatta.... Sose gondoltam volna erre. (Jóhogypersze az első sor "#!/bin/bash")

Akkor ra b@xtal.

coreutils resze, ebbe van a true, false, uname, ls ..
Nem hisszem, hogy valaki letrolne az env-et, hogy nyerjen par kilobytot es szivassa sajat magat es masokat.

Barki akinek egy kis esze van, nem teszi az env -et mashova, vagy gondoskidik egy linkrol.

Nem tudom van -e torveny arrol, hogy hol kell az env -nek lennie, de ha nincs majd ir valaki ;)

Amit nem lehet megirni assemblyben, azt nem lehet megirni.

Két különböző dolog keveredik:

a) paraméterezhető-e az env. A válasz határozott igen, lévén maga az env pont arra szolgál, hogy egy másik alkalmazást az eredetitől eltérő környezetben (environment) futtassunk, pl így: env EDITOR=emacs visudo (ekkor az eredeti - esetleg nem is létező - EDITOR változótól függetlenül az EDITOR=emacs környezeti változóval indul a visudo, és nevével ellentétben nem a vi-jal, hanem az emacs-csal kellene szerkeszteni a sudoers fájlt).

b) a shebang (#!) sor kernelbeli működése, amiről a pontos linuxos megvalósítás eltérhet, de legalábbs a UNIX-világban *deklaráltan* az van, hogy a shebang után egy teljes elérési útvonallal adott, futtatható jogú program neve állhat és maximum egyetlen paraméter, mindez ráadásul nem lehet több X byte-nál - a begépelt szóközökkel együtt. (X jellemzően csak 128, de van ahol 1024)

Ebből következik, hogy a


#! /usr/bin/env perl -ne

azért nem a várt eredményt adja, mert a "-ne"-t a kernel oda se adja az env-nek.

Linuxon nem tudom kipróbálni, csak FreeBSD-n, de a b) pontot kiegészíteném:

$  cat teszt
#!/usr/bin/env bash
echo Teszt
$  ./teszt
Teszt

Ez nem meglepő.

$  cat teszt2
#!/usr/bin/env -S bash -x
echo Teszt
$  ./teszt2 
+ echo Teszt
Teszt

Azaz a -S opció pont azt teszi, amit (szerintem) ubul_ akar, azaz az env által meghívott parancs kap egy opciót.
A -S nélkül viszont nem azt kapjuk, amit vele:

$  cat teszt3
#!/usr/bin/env bash -x
echo Teszt
$  ./teszt3 
env: bash -x: No such file or directory
Exit 127

Vagyis nem nyit egy uj shell-t hanem a jelenlegibe "source"-olja be a parancsokat. Talan erthetobb egy scriptben:

command1
command2
. other_script
command3
command4

Ebben az esetben az "other_script" tartalma olyan mintha ide lenne copy-paste-elve (vagy mondhatnam be lenne source-olva).

Es amugy bash-ban konkretan source-nak hivjak (de mukodik ponntal is):

command1
command2
source other_script
command3
command4

Óvatos finomítás:

A parancsot az eredeti Bourne-shellben .-nak hívták, míg a C-shellben source-nak. A Bash megalkotói szokás szerint innen-onnan beemeltek funkciókat, így a lehetőség mind a két néven elérhető. Az meg az ő szokásos faszságukat (*) bizonyítja, hogy noha a Bash szintaxisa mondjuk 99%-ban (100?) a Bourne-shell szintaxisával egyezik meg, azért ennél a parancsnál dokumentáció szintjén igyekeznek sugallni a C-shellbeli formát. Eredménye, lehet, hogy a script simán képes lenne Bourne-shellben is futni (mert csupa olyan konstrukciót használ, abban a formában), de ha valaki a C-shellből átvett source-ot beleírja (a . helyett), máris hordozhatatlanná válik.

(*) van még pár hasonló "csakazért se leszek kompatibilis meglevő elődeimmel" ökörsége a Bash-nak (bár ezek nagy része inkább Korn-shell, mint Bourne-shell ellenes lépésnek fogható fel)

Nem kellene ennyire óvatoskodni! ;)
Ha megnézzük a programok fejlődését akkor a következő csoportok léteznek. (Ez egy történelmi áttekintés. :))
Ha beírsz egy parancsot, akkor
- kiírja: kopirájt pítör norton -> DOS
- nem ír ki semmit -> unix(szerűség)
- rosseb se tudja mit ir ki -> linux

Következő jellemző: a linux általában önmagával sem kompatibilis, legyen bármilyen kicsi a verzó változása. Ebben egész szépen felfejlődött a windows mellé.

Én jobbára ksh -> bash, sed, grep, awk, sort, ps programokat futtató scripteket szoktam "hordozni". Első feladat a "GNU inkompabilitás" meghatározása az adott linux disztribúcióra/verzióra.

A Bourne-again-be vajon miért kellett belekeverni a C shellt?
A ksh ellenességet meg végképp nem értem. A bash eleinte a line-editing funkcióban volt nagyon erős, bár ennek a magyarázatát nem sikerült megtalálnom - szerintem a legfeleslegesebb dolog. Sokkal hasznosabb lenne, ha a "set -o vi" után nem pattanna vissza egy keverék módba. Eredetileg mindazt nem tudta, amit a ksh, viszont napjainkban már túl is szárnyalja, legalábbis a 15-20 évvel ezelőtti verziót.

A "." jelentése "include". Ezt értem. A "source-olni" azt meg nem. :)

python2 vagy python3? Csak mert a hordozhatóságról az jutott eszembe, hogy mintha már valami kiíratásra szolgáló parancsban is lenne különbség fenti két változat között. Ráadásul ugye van Linux terjesztés, amiben még mindig py2 van (és lesz 2020-ig) alapból, másikban mintha már py3, és ami nem is Linux, hanem *X, abban meg kb egyik sem.
/OFF

Általában python2, mert jelenleg nagyon sok distro-nak az az alapértelmezése, és a /usr/bin/python egy link a /usr/bin/python2 -re. Való igaz, a Python 3-ban a print egy függvény 2-ben pedig utasítás (ezért 3-ban ki kell tenni a zárójeleket).

Lehet úgy írni benne programot, hogy python 2-ben és 3-ban is működjön feltéve hogy betartasz néhány egyszerű szabályt. Csak az alap dolgokat használod (os.listdir, os.stat, subprocess és még néhány), csak ascii string-eket használsz stb. Egy shell script-hez képest így is nagyságrendekkel könnyebb programozni, és szándékosan is nehéz benne csúnya kódot írni.

Ha pedig mindenáron egy adott verzióhoz akarsz ragaszkodni akkor:

import sys
assert(sys.version.startswith('2.'))

és ha valaki véletlenül rossz interpreterrel indítja el, akkor látja hogy mi a gond.

Jajj... Kis naívak!

Bourne shell mindenütt van -> Régebbi (de talán még akár mainál is! Majd Zahy pontosít) FreeBSD alapinstall? -> Nincs
Python* -> Akár a fenti példa. De hozhatnám az AIX régebbi verzióit, vagy akár random bármelyik HP-UX-ot is... -> Luk!

Ha hordozhatóság kell, akkor bizony nem nagyon van más választásod, mint elolvasni, hogy mit ír a posix,
és #!/bin/sh -val kezdesz.

Meg reménykedsz.
Pl. gnu coreutils is rendesen beleszart a ventillátorba magas ívből posix-et illetően.
Elég csak azt megnézni, hogy hogyan tudsz pl. valami fájlt a 20. sorától kezdve felolvasni:
* posix szerint tail +20,
* gnu cuccokkal tail -n +20
Vagy tegyük fel, nem elég neked a basic regexp, és extended kell.
gnu grep-nek van -E opciója.
Posix is előír -E -t.
De vannak unixok, ahol a path elején lévő grep nem tud -E-t, és egrep nincs a path-ban.
De ettől még posix compliant-ok, mert a posix megengedi, hogy a "jó grep" a /opt/xpg4/bin/grep -legyen.
Éééés, kezdheted avval a scripted, hogy:
if printf "valami teszt" | grep -E ... ; then
GREP=...
elif ...
...
fi

És amikor grep-elni kell, akkor $GREP ...

Ha lokál' variable is kell, meg hordozható kód:
a: szívás
b: teszel a kód elejére némi snippetet, hogy háátha van mégis valami értelmes kiutad:

if type local;
then
:
elif type bash;
then
exec bash $0 "$@"
elif type ksh;
then
exec ksh $0 "$@"
else
printf "You have really fucked up\n" >&2
exit 2
fi

Kipróbálhatnád a ksh-t! Számomra teljesen tiszta a szintaxisa.
Talán egyszer én is kipróbálom a python-t. Megírom az 1992-ben ksh-ban és c-ben, aix-re készült programot az akkori python verzióban (ami biztosan fut aix-en), aztán lefuttatom egy mai linuxon. Valószínűleg meglepetés lesz a kompatibilitás és a sebesség. :)
Azért a hordozhatóságnak van olyan ismérve is, hogy egy oprendszer upgrade esetén nem kell újraírni a programokat. (Ilyenben az IBM elég jó szokott lenni. Ráadásul pontosan dokumentált!)
A komplikált és python összefüggés azért nem teljesen triviális. Ilyen esetben sokkal okosabb dolog a feladatot egyszerűsíteni és apróbb részletekre bontani. Az így előállt részletekből tetszőleges feladat megoldása összerakható. (Ez a klasszikus unix eszközök egyik fő jellemzője.) A jó algoritmus tetszőleges eszközökkel megvalósítható, de ebből nem következik, hogy tetszőleges eszköz optimális. Pl. egy shell script is átírható sql-be. Az ilyen megoldás nem példa nélküli, de azért elég ritka. ;)

:)
Akkor bizonyára ezt is ismered: A munka ára 10000Ft. A kalapácsütés 1Ft, a többi meg az, hogy tudom hova kell ütni.

Két fiatal (>30) programozónak egyenként, egy mondatban elmondam mit kell csinálni. (Ne szólj bele bucko bácsi! Ez C#, nem értesz hozzá!) Két hónap elteltével kaptam egy visszajelzést, miszerint adatok vesznek el. Írtam 8-10 sor - összesen 2 thread - programot, amit bekopipészteltek, (Bár előtte kételyek ébredtek, hogy ez mitől is működne.)
Ezek után a két ember letöltött valami lassító programot, amivel a corei7 3,5 magját leterhelték, osztán még mindig hibátlanul működött.
(Tájékoztatásul: hármunk közül én vagyok a hardverfejlesztő és assembler programozó.)

Úgy gondolom, enyém a kalapács és a 9999Ft. :D

Szóval hidd el, a python is pont olyan eszköz, mit a többi: lehet benne szarul is programozni.
A fenti példa alapján meg látszik, hogy a feladat megoldása általában a programozó képességein múlik és nem a használt eszközön. Számomra pedig az a megfelelő eszköz amivel meg tudom oldani a feladatot.
Tehát nekem a kalapács az űrhajó, sőt jártam már vele a Holdon is!

Netalán abba a csoportba tartozol, akik tagadják az Apollo program valódiságát, mivel az akkori számítógépekkel ez nem volt lehetséges? ;)

Úgy látom, lassankén kezdünk egy követ fújni. ;)
A példa meg tényleg nem a shell rejtelmeiről szólt. Azt a hibát írtam le, amikor az időzítéseket nem értő programozó polling+sleep technikával próbál eseményt elcsípni - miközben a másik thread-ben (windowson!) grafikont rajzol. Ezt még lehet cifrázni a prioritásokkal, de akkor sem működik. :)

Mi köze ennek a shell-hez? Csak annyi, hogy abban is eseményvezérelt rendszerket írtam. Régen, - amikor még 33 vagy 75MHz-es POWER processzoron futott - jelentős volt a shell futásideje is. A mai sebességek mellett meg elhanyagolható akár >100 páhuzamosan futó feladat mellett is.

Sziasztok,
Nálam változó, saját, munkakönnyítő scriptekbe függvényeket írok, azokat source-olom, külső scripteket pedig átolvasás után funkció szerint kezelem :)
Üdv,
LuiseX

Általában az első módon.
Ha nem kell gyakran futtatni és jobb ha nincs futtatható fájl attribútuma, akkor a második módon.
--
Tertilla; Tisztelem a botladozó embert és nem rokonszenvezem a tökéletessel! Hagyd már abba!; DropBox

Szkriptből:
/sbin/ennek-kell-futnia.sh
Terminálból:
ennek-kell-futnia.sh vagy enn + 2 Tab + Enter

;)
OW

Ha olyan, hogy nem csinál veszélyes dolgot és bárki futtathatja, akkor ./ennek-kell-futnia.sh
Ha kicsit is izgalmasabb, akkor nincs rajta execute jog és /bin/bash ./ennek-kell-futnia.sh (a kevéssé képzett kollégák nem tudnak véletlenül rátenyerelni).

Attól függ. Céges laboron/tooloknál source.
Saját development masinán ./valami
--
"Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live." John F. Woods

Get dropbox account now!

bash ennek-kell-futnia.sh

Miért lenne jobb a bash ./ennek-kell-futnia.sh (eltekintve attól az esettől, ha fájl neve megegyezik vmi bash kapcsolóval)?

Hogyan szoktál levegőt venni?
- Mellkas mozgatásával.
- Vastüdővel.
- Alkuszom a piacon.
- Spórolok.
- Egyéb leírom.
;)
Jól csoportosított kérdések!

Egyébként az utolsó.

ksh -c full_path/ennek-kell-futnia

Ugyan ez egy szavazás, de.
Ha valaki úgy általában futtat scriptet, akkor általában "egyéb módon/attól függ" lehet igaz.
A többi esetben meg nem szokott rendszeresen, többféle scriptet futtatni.
Ezért elég hamis lehet ez a statisztika.

egyeb:
Androidon sh /script/aminek/futnia/kell.sh, mert pl. az sd kartya ugy van mountolva, hogy futtatni nem fog rola, es ez shell scriptekre is vonatkozik
Otthoni gepen parancssorbol siman ennek-kell-futnia.sh, mert benne van a . a PATH-ban, szoval a ./ sem kell ele
Scriptbol, amit lehet, hogy mas environmentbol is futtatok, pl.: ~nyos/bin/ennek-kell-futnia.sh modon, mert csak en piszkalom oket, de sokszor bootnal nincs beallitva minden

Masnak ritkan irok scriptet, olyankor a 3. modszer nyilvan nem jatszik, ahogy a masfele shellre sem szoktam figyelni, mert eddig nem volt ra igenyem.

--
Is that a banana in your pocket, or are you just happy to see me?
Neither, it's my new iPhone.

Ilyen alapon az is érdekes, hogy a /lib/ld-linux.so.2 és a /lib64/ld-linux-x86-64.so.2 is lefuttat neked i386 ill. x86-64 dinamikusan linkelt binárist, akkor is, ha nincs rá exec jog.

De igaziból nem, nem az. (Mármint nem érdekes!)

Ez tudott!

Én inkább azon kamillázom, hogy van még olyan bátor ember, aki a .-t beteszi a PATH-ba.
Na, aaaaz bátor!

Nagy vonalakban ezektől függ:
- Execute jog van-e rajta?
- PATH-ban benne van-e?
- Tudom-e, hogy milyen dialektus?
- Kíváncsi vagyok-e némi plusz infóra? (sh -x)

A gyakorlatban a leggyakrabban ilyen a döntés eredménye: python myscriptinthecurrentfolder.py

_______Peter
I am a stone. I do not move.

Egyik sem. Nálam nincs nyelvfüggő postfixe a fájlneveknek. Először megírom bash scriptként, aztán lehet, hogy később kellemesebb mondjuk Perlben fejleszteni, így átírom. A használóinak ne kelljen szöszölnie azzal, hogy milyen nyelven írtam. Így is, úgy is ./ennek-kell-futnia


curl -sL http://random.website/script.sh | sudo bash -

crontab
csak akkor írok scriptet, de akkor akár többsorosat is...

Rákattintok duplán.

--
Fontos! Ha berágok, nem feltétlen személyed ellen szól...
openSUSE 42.1 x86_64

Nyelv-neve elérési-ut abszolút vagy relatív ha szükséges stdio kezelése célja

~/bin és ~/sh a $PATH része nálam, így elérési út nélkül is megy, mivel itt tárolom a saját állományokat.

attól függ... egy részüket előbb-utóbb bemásolom az /usr/bin -be, aztán

ennek_futnia_kell.sh

-fs-
Az olyan tárgyakat, amik képesek az mc futtatására, munkaeszköznek nevezzük.
/usr/lib/libasound.so --gágágágá --lilaliba