Fórum Root.cz

Hlavní témata => Software => Téma založeno: Ħαℓ₸℮ℵ ␏⫢ ⦚ » 02. 04. 2020, 12:57:07

Název: Kde najít přesnou formu spuštěného programu?
Přispěvatel: Ħαℓ₸℮ℵ ␏⫢ ⦚ » 02. 04. 2020, 12:57:07
Mám takový problém, pokouším se najít přesné znění příkazu, které jsem zadal do lxterminálu (ale nedostanu se do něj z plochy už! GUI shořelo)
Zadaný příkaz je rsync "petr novak" "pavel jungman" josef cifis - důležité na něm je jen uvozovky a mezery
První pokus
Nicméně vcat /proc/123456/cmdline vidím ,že způsobí:
- mezery nahradí hexaznaky 00
- uvozovky odstraní
- na konec přidá null znak

Takto je to nepoužitelné, když chci příkaz znovu oživit (třeba zkopírovat do schránky v přesném zněí). Například nano editor tam vybleje ^@., textový editor Mousepad ho ani neotevře, skončí na chybové hlášsce o nepodporované znakové sadě, maximálně si ho mohu otrevřít jako UTF-16 a kochat se čínštinou. V tom nákupním seznamu znakových sad aby se prase vyznalo a  jsem ani nenašel ASCII tam .  Takový editor je zrátka na draka

Chápu že asi jde o nějakou interní reprezenaci příkazu (a asi koherentní). A možná i chápu, že příkaz je interně spuštěn s argumenty ["Petr novak","pavel jungman", "josef","cifis"] a že shell nějak poskytuje konvenci, že mezery jsou separátor argumentů (nejsou-li v uvozovkách)
Druhý pokus byl ps aux | grep pavel - ztratili se uvozovky.

Je nějaká možnost, jak zjistit přesné znění příkazu? Tzn přesně jak jsem ho zadal, aby tam byly správně uvozovky ?

Například:
-nějaká utilita na konverzi proc/cmdline  (sed/awk/preg_replace ... jak escapovat null znak?)
-nějaký parametr ps, který neprzní formu příkazu (zachová uvozovky)
- jiný způsob
Název: Re:Kde najít přesnou formu spuštěného programu?
Přispěvatel: Petr Krčmář 02. 04. 2020, 13:38:15
V paměti procesů už původní podoba příkazové řádky není, protože před spuštěním procesu se stane spousta věcí. Zejména do toho zasahuje shell, který provede expanze, nahrazení, interpretaci proměnných a podobně. Navíc jeden odeslaný řádek běžně vyvolává spuštění více procesů nebo subshellů.

Takže jediný, kdo zná podobu zapsaného příkazu na řádku je shell a ten si ho dá do své historie, odkud se dá získat.
Název: Re:Kde najít přesnou formu spuštěného programu?
Přispěvatel: novotnyr 02. 04. 2020, 15:22:44
Ak to nemáte v histórii, je to stratené.

Pred spustením príkazu totiž shell odstráni úvodzovky (quote removal).

Ak napíšete do shellu:

Kód: [Vybrat]
rsync "petr novak" "pavel jungman" josef cifis
Reálne sa spustí rsync so 4 argumentami a samotný rsync už vo svojich argv netuší, že v shelli existovali nejaké úvodzovky či apostrofy obaľujúce viacslovné argumenty.

Je to úplne rovnaké ako:

Kód: [Vybrat]
rsync "petr novak" "pavel jungman" "josef" "cifis"
Název: Re:Kde najít přesnou formu spuštěného programu?
Přispěvatel: tecka 02. 04. 2020, 15:56:44
Kód: [Vybrat]
</proc/PID/cmdline xargs -0 printf '%q '
Název: Re:Kde najít přesnou formu spuštěného programu?
Přispěvatel: Franta Kučera 02. 04. 2020, 16:00:21
Jestli tě zajímá, jak to funguje uvnitř, tak viz Přepisování parametrů příkazové řádky (https://blog.frantovo.cz/c/362/P%C5%99episov%C3%A1n%C3%AD%20parametr%C5%AF%20p%C5%99%C3%ADkazov%C3%A9%20%C5%99%C3%A1dky).

Parametry programu jsou pole textových řetězců, nic jako uvozovky, apostrofy nebo mezery tam nefiguruje – to je jen způsob zápisu toho pole používaný v shellu.

Ty nulové bajty, které jsi našel v souboru cmdline, nenahrazují mezery, ale oddělují prvky toho pole.

Původní zápis můžeš najít v historii shellu nebo bys mohl udělat dump paměti shellu a vyhrabat to odtamtud, ale to asi nechceš. Spíš bych se tedy smířil s tím, že ten původní tvar je ztracený a rekonstruoval bych zápis v shellovském formátu z toho pole – tzn. obalit uvozovkami či apostrofy a escapovat, případně obalovat jen řetězce, kde je to potřeba (obsahující mezery atd.).
Název: Re:Kde najít přesnou formu spuštěného programu?
Přispěvatel: Ħαℓ₸℮ℵ ␏⫢ ⦚ » 02. 04. 2020, 18:39:43
K prvním 2 odpovědím, to jsem nějak tušil možná  o těch  ztracených uvozovkách. že mezery uvnitř uvozovek zachová, jsem už zjistil před napsáním dotazu (ale nepodělil jsem se  :-[ ) (ale oklikou jsem napsal, že ten tvar je koherentní) (pracovat se souborem historie by byl overkill)

Vlastně tedy mi o uplně přesný tvar nejde (například rsync $source) ale stačí mi argumenty binárky (tedy po escapování a substituci, v příkladu jsem nic takového nepoužil ,takže tento požadavek nebyl dementován)... , ostatně přesně tak jak je vidím v cmdline nebo ps.

a ten trik s xargs "%q " zafungoval (odpověd 1. bod konverze cmdline) ::)
Název: Re:Kde najít přesnou formu spuštěného programu?
Přispěvatel: Ondrej Nemecek 02. 04. 2020, 22:36:46
K prvním 2 odpovědím, to jsem nějak tušil možná  o těch  ztracených uvozovkách. že mezery uvnitř uvozovek zachová, jsem už zjistil před napsáním dotazu (ale nepodělil jsem se  :-[ ) (ale oklikou jsem napsal, že ten tvar je koherentní) (pracovat se souborem historie by byl overkill)

BTW je práce s historií do shellu zabudovaná, v bashi dáte CTRL+R a napíšete třeba diff, uvidíte poslední použitý příkaz diff. Při opakovaných stisknutích CTRL+R pak vidíte i předchozí výskyty v historii. Případně lze použít něco jako

Citace
# grep "diff" ~/.bash_history | tail -n1
Název: Re:Kde najít přesnou formu spuštěného programu?
Přispěvatel: Vít Šesták (v6ak) 04. 04. 2020, 10:13:17
Ta varianta s xargs -0 a print "%q " je asi to nejpřesnější, co dostanete z běžícího procesu. Escapuje to parametry pro bash, ale samozřejmě to nezná přesnou původní formu ("foo bar" vs. 'foo bar' vs. foo\ bar). Nebudou tam různá přesměrování do/ze souboru (i když, to by se možná taky dalo nějak dohledat).

Například z příkazu:

tail ~/something | grep foo > bar

uvidíte zvlášť tail (s expandovaným ~) a zvlášť grep foo. Přesměrování do souboru bar by možná šlo dohledat jinde, v cmdline to nebude.
Název: Re:Kde najít přesnou formu spuštěného programu?
Přispěvatel: Filip Jirsák 04. 04. 2020, 14:42:16
Přesměrování do souboru bar by možná šlo dohledat jinde, v cmdline to nebude.
V otevřených file descriptorech bude odkaz na obsah toho souboru. Ale jaká byla původní cesta k tomu souboru nezjistíte – on už ten soubor nemusí mít v souborovém systému jméno (může ho držet už jenom ten proces), nebo dokonce pod tím jménem může být v souborovém systému jiný soubor.