Bash subshell hatterben ellopja a promptot

Fórumok

Sziasztok,

Van otletetek arra, hogy ha egy subshellben hatterben futtatok egy parancsot, hogyan szerezzem vissza enter leutese nelkul a promptot?

pl: ( ls & )

Elore is koszi a valaszokat.

cU

Hozzászólások

Androidon ez működik, máshol most nem tudtam kipróbálni:

echo | ( ls & )

És nem is jó. Elsőre működött, utána már nem.

update: na jó, lassanként csak felébredek... :)
Szóval annyi a történet, hogy ha parancssorból indítasz egy background processzt, ami ír a stdout/stderr eszközökre, akkor az enter megnyomása után rögtön megkapod a promptot, csak a háttérbe tett processz még utána írja a saját szemetét.

Tehát amit tenni lehet, hogy átirányítani a háttérbe tett programok kimenetét valahova, hogy ne az aktuális konzolra szemeteljen.

Én arra tippelek hogy a probléma gyökere ott van, hogy a derék ember elindít mondjuk egy mplayert a háttérben, és utána küzd a terminálban makacsul megjelenő sorokkal. Ha tényleg így van, akkor a screen lehetne jóbarát (vagy van még egy valami, ami olyan mint a screen, de nem az, de majdnem ugyanaz, de vagy jobb vagy nem, de az biztos).

Nem az a baj, hogy nem ez a szabályos, hanem így nem jó. Pl. A cp parancs, ha paraméter nélkül hívod, az stderr-re dob hibaüzenetet. Ha jól tippelem, te mind a stderr-t, mind az stdout-ot át akarod irányítani. Vizont mivel a paranccsor feldolgozása balról jobbra történik, a te megoldásoddal először az stderr-t átirányítod oda, ahova az stdout (az átirnyítás pillanatában) megy. Ez a képernyő. (Azaz a képernyőről a képernyőre.) Utána az ettől független stdout-ot a fekete lukba. De attól még a hibaüzenet látszik a képernyőn. Ahogy én írom (javaslom), úgy mind a kettő megy a devnullba.

$ cp a 2>&1 > /dev/null
usage: cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpvx] source_file target_file
cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpvx] source_file ... target_directory
$ cp a > /dev/null 2>&1
$

A program amit hatterben futtatok, kb 2-3 mpig fut, /etc/profile-bol aztan kiir vmit.

Nem szeretnem a logint hatraltatni azzal h a usernek varnia kelljen mig lefut, ezert subshellbol futtatom hatterben, de mivel biztos vagyok benne h lesznek olyanok akik reklamalnak majd, h meg egy entert kell nyomniuk ezert gondoltam hatha nektek van otletetek.

- Ennel fogva sajnos a sleepes megoldas nem jo.
- Valtozot nem tudsz kihuzni subshellbol.
- Fileba atiranyitva ugyanott vagy, hiszen egyszer ki kell irni. Esetleg job controllal lehet jatszani, h amint a processem lefutott kicatelem a filet es letorlom. Mondjuk szeretnem tempfile nelkul megoldani.

egmont kérése arra vonatkozott, hogy ha nem várod meg a 20 secet ilyenkor, a user meg már dolgozik, akkor mit szeretnél:
- beleszemetelni a te vackodat a munkája közepébe, mert fontos (vállalva, hogy fogalmad sincs, épp mi van a képernyőn, uh zagyva lehet, ill tuti sűrűn fogsz csuklani)
- ilyenkor már inkább letojni, amit ki akar írni.

my 2 cents, hogy ilyet inkább ne csinálj loginkor.

Nem voltam teljesen preciz, mert van egy 3 masodperces timeout a curl-on, szoval max 3 masodperc telik el a script futasa es az adatok kiirasa kozott, ha tobb akkor exit 1.

Arrol lenne alapvetoen szo, h ha a szerver monitorozva van akkor ezt kiirja, igy az adminok tudjak, h ovatosan barmifele valtoztatassal...

Még mindig nem érted a kérdésemet. Tegyük fel, a felhasználó nem várja ki ezt a 3mp-et, hanem már elkezd dolgozni. Vagy elkezdte már begépelni a parancsot, vagy esetleg le is ütötte az entert és elindította kedvenc programját ilyen gyorsan. Ez után letelik a 3mp és a curl-nak közlendője támad. Mi történjen, hogyan képzelted el???

Ha a shell history megmarad két belépés között, akkor onnan akármit is vissza lehet szedni és elindítani. Egyébként meg mi van, ha az ssh banner-t és/vagy a motd-t állítgatod attól függően, hogy épp milyen státuszban van a szerver? Mondjuk a gond ezzel ott van, hogy a monitoringnak kéne odaszólni az adott gépre, hogy átbillentették az állapotát.

http://hup.hu/node/132219#comment-1729579
Kb. ezt feszegettem, csak ennyire nem részleteztem az ötletem. De arra is rájöttem, hogy nem 100%-os módszer (kérdés, mennyire kell betonbiztosnak lennie?)

A motd és hasonlók azért nem jók (szerintem - de ez csak utólag jutott eszembe), mert ha már be van jelentkezve a delikvens, akkor nem fog értesülni a váltásról. És amíg élesből maintenance módba kapcsolnak, addig nem is baj, max. telefonálgat feleslegesen az admin kolléga, de ha akkor kapcsolja vissza valaki élesben, mikor be van jelentkezve és tovább dolgozik abban a hitben, hogy még mindig lehet...

Szóval erre valami olyan megoldás kellene, ami azonnal értesíti a bejelentkezett usereket is.
Még1x: szerintem.

A monitoring mindig fut. A script lekerdezi h a gep eppen aktivan van-e monitorozva vagy esetleg maintenance modban van.

A dolog lenyege az, hogy megelozzem h az adminok a gep maintenance modba rakasa nelkul csinaljanak vmit, ami ticketet generalna a monitoring teamnek.

A statusz lekeresen kivul annyit tud a cucc, h commandlinebol tudod maintenance-be rakni a gepet es nem kell kattintgatni a webes feluleten hozza.

Ha előveszem a gépem, majd írok pár szót, mert szerintem ez így nem túl jó ötlet. Csak ne felejtsem el...

Elővettem... :)
Szóval ha a monitorozó szoftver ezt lehetővé teszi, akkor valami olyasmit csinálnék, hogy amikor maintenance módba kapcsol, akkor ezt jelzi pl. egy fájl létrehozásával a felügyelt rendszeren, amikor visszavált élesbe, akkor törli a fájlt (vagy fordítva)
Így csak üzemmód váltáskor kell foglalkozni vele és nem kell trükközni a belépéskor lefutó szkriptben, mindössze ellenőrizni kell a fájl létét/esetleg tartalmát.
Másik tippem az lett volna, hogy ne a stdout-ra küldd az üzenetet, de ez már macerásabb, mert X-es felületen még lehet valami üzenetet feldobni, de ha ssh-n megy be... (régi, szép idők, VT220-as vagy nagyobb terminálok, ahol volt státusz sor, ahova ilyesmit ki lehetett volna nyomni egy ANSI escape szekvenciával... :) )
Szóval ssh-n nem nyerő, mert bármit csinálsz, ugyanúgy beleszemetel a képernyő tartalmába és nyomkodni kell az entert, hogy lásd a promptot.

koszi :)

Az a gond, h ugye a webes illetve a nativ feluletrol is maintenancebe lehet rakni a gepet es ezt vhogy detektalnom kell az sshs belepes soran.

Jelenleg ugy oldottam meg, h letarolom a kurzor pozicoit, kiirok egy kamu promptot es visszarakom a kurzort a vegere. Nem tul szep megoldas sajna :/

Még egy tipp jutott eszembe: a belépéskor háttérben lefutó program is létrehozhatna egy fájlt a user saját könyvtárában és (már nem emlékszem, hogyan) a promptot is be lehet állítani úgy, hogy minden megjelenítése előtt futtasson le egy parancsot, ami átalakíthatja magát a promptot is.
Így lehet valahogy megoldani, hogy pl. git repoba tartozó könyvtárba lépve a prompt mutassa, hogy pl. melyik branch aktív az adott helyen. (nem tudom, érthető-e, hogy miről beszélek)

Nem. Minden alkalommal lefut, amikor a promptot generálja. Ennek az az oka, hogy a promptot a $PS1 kiíratásával teszi ki, viszont a PS1-ben van olyan helyettesítés, ami kódot futtat.

Amit mondok, abban biztos vagyok, mert így írom ki az előző parancs exit kódját sárgával a promptomba, ha viszont az exit kód nulla, azt nem íratom ki, hiszen az a normális.

PS1='\[\e[m\][`RET=$?; [ $RET -ne 0 ] && echo "\[\e[33;1m\]$RET\[\e[m\] "`\u@\h \w]\$ '

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Figyelj!

PS1="$(pwd) > "
PS1='$(pwd) > '

Az első forma az értékadáskor futtatja le a pwd-t, tehát tulajdonképp konstans promptod van. A második az értékadáskor nem futtat semmit, ellenben a prompt minden aktuális kiírásánál igen, tehát mindig a helyes PWD látszik.

(A pwd parancs példa, *tudom* hogy bash-ban ezt lehet millió más módon is.)

Ha idézőjelek (") közé teszel egy stringet, akkor a shell kifejti a benne található $ kezdetű részeket és e szerint a backticket is.
Ha aposztrófok (') közé, akkor ez a helyettesítés elmarad.

Ez nem a prompting szakaszban van leírva, hanem... na ezt majd Zahy, nekem nem jut eszembe.

update: Quoting a man bash alatt. És rosszul emlékeztem, úgy tűnik, a backslash kezdetű spec. karaktereket is behelyettesíti idézőjelek közt...

A kérdést se értem. A modern shellek, ha a PS1-ben parancshelyettesítést látnak, akkor prompt kiíráskor azt végrehajtják. Az, hogy mi módon rakom be a helyettesítést, tök mindegy, így is tehetném:

PS1=\$\(pwd\)\ \> \{space}

Az aposztróf mindig takar mindent, az idézőjel meg pl. pont az öszes dollárjeles helyettesítést ($v, ${v}, $(cmd), $(( kif )) - vagy helyette $[ kif ] ) - és persze a backtick-kel is ugyanígy - megcsinálja még a parancssor feldolgozásakor.

Köszönöm, így már világos.

Azt nem tudtam, hogy lényegében olyan ez, mint az eval. Egyszer végrehajtódik értékadáskor, utána pedig az értékadáskor keletkezett produktum minden egyes prompt kiírás alkalmával értelmezésre és végrehajtásra kerül.

Tehát, ha jól értelek, aposztrof esetén értékadáskor marad a futtatható kód, ami a prompt kiírásakor végrehajtásra kerül.

Idézőjel esetén pedig az értékadáskor már lefut a kód, majd a keletkezett statikus string kerül kiíratásra a prompt kiíratásakor.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE