Kde najít přesnou formu spuštěného programu?

Kde najít přesnou formu spuštěného programu?
« kdy: 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
« Poslední změna: 02. 04. 2020, 13:33:35 od Petr Krčmář »


Re:Kde najít přesnou formu spuštěného programu?
« Odpověď #1 kdy: 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.

Re:Kde najít přesnou formu spuštěného programu?
« Odpověď #2 kdy: 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"

tecka

  • ***
  • 138
    • Zobrazit profil
    • E-mail
Re:Kde najít přesnou formu spuštěného programu?
« Odpověď #3 kdy: 02. 04. 2020, 15:56:44 »
Kód: [Vybrat]
</proc/PID/cmdline xargs -0 printf '%q '

Re:Kde najít přesnou formu spuštěného programu?
« Odpověď #4 kdy: 02. 04. 2020, 16:00:21 »
Jestli tě zajímá, jak to funguje uvnitř, tak viz Přepisování parametrů příkazové řádky.

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.).


Re:Kde najít přesnou formu spuštěného programu?
« Odpověď #5 kdy: 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) ::)

Re:Kde najít přesnou formu spuštěného programu?
« Odpověď #6 kdy: 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

Re:Kde najít přesnou formu spuštěného programu?
« Odpověď #7 kdy: 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.

Re:Kde najít přesnou formu spuštěného programu?
« Odpověď #8 kdy: 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.