Záchrana historie z existujícího Bashe

Záchrana historie z existujícího Bashe
« kdy: 05. 11. 2025, 23:48:59 »
jak zachránit historii z běžícího bashe ? Ten bash byl spuštěn v době dřív kdy načetl histfile z dřívějška. Tudíž v něm je otisk history . Nyní  je $HISTFILE přepsaný. Bohužel aktuální bash skončil.

0. ten bash proces stále beží, loginctl ho má pod sebou v exited session která šla přes ssh. asi má uzavřené IO. (exited asi 2 dny) ale pořád visí

metoda 1. Udělal jsem si gcore PID a přes strings/nano/less vidím položky historie=částečný úspěch ale v strings roztroušené a v různém pořadí asi a uvozené stringy číslem unix timesamptu #17....... (což popírá, že jsou roztroušené v jiném pořadí), nano zase mám spoustu balastu, nonprintable chars a taky nevidím vše pohromadě.

 ..... ls -l /proc/PID/fd  ukazuje u 0 1 2  položek cíl pts/1 (deleted) je to problém -   heknout se na stdin stdout když proc fd ukazuje deleted ?

Jak na to ???
2 cesty mě napadají:

1 gdb -p běžící bash. a nějak tomu procesu oživit stdin a stdout (nebo prostě zavolat funkci "intepretuj příkaz history")a pokusit se zapsat history a čekat s chřtánem na stdout. AI mi k tomu napsala třeba call (int) system("ls") - bojim se že to je ekvivalent exec ls a to víme co s bashem udělá.... fungovalo by syste(history) ? kde uvidím stdout ..Nebo přes nějaké duplikování deskriptorů



metoda 2: parsing  core dumpu( který jsem si i přes gcore udělal pro případ, že třeba vypne se proud  ::) ).. s využitím  gdb gdb bin/bash corefile ; print history_list ; x/20s 0x67...123 jak mi to radilo ale nevidím nic čitelného

Citace
0x622212369770 <history_list>: "\363\017\036\372H\213\005\255o\005"
0x62221236977b <history_list+11>:       "\303\017\037@"
0x622212369780 <current_history>:       "\363\017\036\372Hc\025\211o\005"
0x62221236978b <current_history+11>:    ";\025\177o\005"...
0x6222123697a8 <current_history+40>:    "1\300\303\017\037D"
0x6222123697af: ""
0x6222123697b0 <previous_history>:      "\363\017\036\372\213\005Zo\005"
0x6222123697ba <previous_history+10>:   "1҅\300t\026\203\350\001H\213\025^o\005"
0x6222123697ca <previous_history+26>:   "\211\005Do\005"
0x6222123697d0 <previous_history+32>:   "H\230H\213\024\302H\211\320\303f\017\037D"
0x6222123697df: ""
0x6222123697e0 <next_history>: "\363\017\036\372\213\005*o\005"
0x6222123697ea <next_history+10>:       ";\005 o\005"
0x6222123697f0 <next_history+16>:       "t\036\203\300\001H\213\025,o\005"
0x6222123697fc <next_history+28>:       "\211\005\022o\005"
0x622212369802 <next_history+34>:       "H\230H\213\004\302\303\017\037\200"
0x62221236980d <next_history+45>:       ""
0x62221236980e <next_history+46>:       ""
(gdb)

3. má přímo bash někde v paměti proměnnou obsahující string $HISTFILE
4. je problém dostat z toho core dumpu správné pořadí té historie, protože půjde o nějaký linked list, ještě případně zpřeházený podle toho jak se ignoredups příkazy posouvají na konec. ?

HISTORIE má defaulních 500 položek.
« Poslední změna: 05. 11. 2025, 23:55:11 od Ħαℓ₸℮ℵ ␏⫢ ⦚ »


Ink

  • *****
  • 698
    • Zobrazit profil
    • E-mail
Re:jak zachránit historii z existující bash (gdb)
« Odpověď #1 kdy: Dnes v 06:54:11 »
Je to off topic, ale lidi, používejte konečně fish, kde to jde...

Re:Záchrana historie z existujícího Bashe
« Odpověď #2 kdy: Dnes v 11:31:46 »
Dotaz: pokud mám ten core dump , je možné z něj nějak jen uložit menší výsek paměti ( jako je anotovaný kus toho výpisu<current_history><prev_history>,<next_history> a <history_list>) , abych musel procházet méně balastu přes strings/hexdump? On má 2900kB nebo 4500kB (gcore -a)
Kód: [Vybrat]
root@x:~/core# (strings core|sort|uniq) |wc
  13921   19899  220162
root@x:~/core# (strings core-a|sort|uniq) |wc
  18201   24637  244798
...  diff -y  <(strings core|sort|uniq) <(strings core-a|sort\uniq) |less...... motají se tam i completions
 
SIce je to OT  od záchrany dataco ten fish umí zázračného ? Problém je, že 1 jsem neměl nakonfigurovaný pořadně .bashrc   (HISTSIZE na 20000 by jen oddálilo problém nebo by mi jen zaneřádilo HISTFILE třeba jen 1500 řádky), jen ignoredups, nemám append nebo ten PSPROMPT na chytré slučování (problematika na korektní  zápis do historie pokud běží víc bashů současně)...
Ale tohle je prostě moje blbost, že jsem copy paste scriptu do terminálu nezavolal unset HISTFILE (a i tak si nejsem jistý že by to na 100% pomohlo, ten skript mohl  si spustit novou instanci bashe nebo co já vím) a ten skript zřejmě někde měl řádek exit nebo jiný return, který uzavřel aktuální bash a zapsal historii (který byla vyšší než 500 řádků) ...Situace taková je, že nyní HISTFILE obsahuje posledních 500 řádků toho copy paste skriptu. fujtajbl
« Poslední změna: Dnes v 11:40:23 od Ħαℓ₸℮ℵ ␏⫢ ⦚ »

tecka

  • ***
  • 176
    • Zobrazit profil
    • E-mail
Re:Záchrana historie z existujícího Bashe
« Odpověď #3 kdy: Dnes v 11:47:37 »
To, že vidíš history_list by mělo stačit i pokud nemáš nic víc. To je funkce vracející ukazatel na uloženou historii, což je pole ukazatelů na HIST_ENTRY, ve které první položka je string.
Kód: [Vybrat]
(gdb) call ((void*(*)(void))history_list)()
$1 = (void *) 0x555555a2fd20
(gdb) p *(char**)(((void**)0x555555a2fd20)[0])
$2 = 0x55555577b390 "cd .."
(gdb) p *(char**)(((void**)0x555555a2fd20)[1])
$3 = 0x5555556e6e20 "ll"
(gdb) p *(char**)(((void**)0x555555a2fd20)[2])
$4 = 0x55555579fdf0 "make CFLAGS=\"-O0 -ggdb\""

Re:Záchrana historie z existujícího Bashe
« Odpověď #4 kdy: Dnes v 12:13:23 »
Skvělé... (nefunguje to sice na gdb uleželého core dump,abych nic nepokazil, ale zkouším to na jiné instanci běžícího bashe),ale budu tomít i očíslované a s pořadím . super
Jen mě zajímá, pro automazaci:
1. je možné obsah příkazu "p" uložit do souboru z gdb abych se neuklikal nebo to nekopíroval scrollbuffer terminálu a složitě to neparsoval
2.je možné použít příkaz "p" na steroidech, aby vypsalo přímo celé pole  naráz?


právě teď asi kixnul ten počítač, jak jsem to te´d zkoušel umřel ssh spojení a nejde ping ! je možné že to crashlo kvůli přistupu do paměti? EDIT: otázka platí, je možné tímto shodit celý PC (ne jen bash) .. Cant access memory
Kód: [Vybrat]
Cannot access memory at address 0x31303d6d722e2a3a
(gdb)  p *(char**)(((void**)$1)[25])
(gdb)  p *(char**)(((void**)$1)[1])
$2 = 0x5d376548cfd0 "\t\t\t\t\tstatusLine += 'Output: <span>' + actualWattage + 'W</span>';"


Cannot access memory at address 0x31303d6d722e2a3a
(gdb)  p *(char**)(((void**)$1)[299])
Cannot access memory at address 0x31303d687a6c2e2a
(gdb)  p *(char**)(((void**)$1)[29])

Uff, jsou to nějaký glitše v síti , vypadává asi kabel-link-utpčko
Kód: [Vybrat]
10x za posledních 3 minuty, předtím ne
vmbr0: port 1(enp2s0) entered forwarding state
igc 0000:02:00.0 enp2s0: NIC Link is Down
vmbr0: port 1(enp2s0) entered disabled state
igc 0000:02:00.0 enp2s0: NIC Link is Up 100 Mbps Full Duplex, Flow Control: RX/TX
vmbr0: port 1(enp2s0) entered blocking state
vmbr0: port 1(enp2s0) entered forwarding state
igc 0000:02:00.0 enp2s0: NIC Link is Down
vmbr0: port 1(enp2s0) entered disabled state
igc 0000:02:00.0 enp2s0: NIC Link is Up 100 Mbps Full Duplex, Flow Control: RX/TX
vmbr0: port 1(enp2s0) entered blocking state
vmbr0: port 1(enp2s0) entered forwarding state
igc 0000:02:00.0 enp2s0: NIC Link is Down
vmbr0: port 1(enp2s0) entered disabled state
igc 0000:02:00.0 enp2s0: NIC Link is Up 100 Mbps Full Duplex, Flow Control: RX/TX
vmbr0: port 1(enp2s0) entered blocking state
vmbr0: port 1(enp2s0) entered forwarding state
igc 0000:02:00.0 enp2s0: NIC Link is Down
vmbr0: port 1(enp2s0) entered disabled state
igc 0000:02:00.0 enp2s0: NIC Link is Up 100 Mbps Full Duplex, Flow Control: RX/TX
vmbr0: port 1(enp2s0) entered blocking state
vmbr0: port 1(enp2s0) entered forwarding state
« Poslední změna: Dnes v 12:20:26 od Ħαℓ₸℮ℵ ␏⫢ ⦚ »


Re:Záchrana historie z existujícího Bashe
« Odpověď #5 kdy: Dnes v 13:02:21 »
OK POVEDLO SE. přímo v gdb: set logging on ; a klasicky while $i <500 {p   p *(char**)(((void**) 0x62222b86fc70)[$i] ; $i+=1;) end

Re:gdb print vs call
« Odpověď #6 kdy: Dnes v 14:34:36 »
Mimochodem jaký je rozdíl mezi print a call? Nějak mi nesedí vysvětlení ai, že jedno volá a může mít side affecty a druhé je jen evaluace.

Avšak mé netrénované gdboko nevidí rozdíl
Kód: [Vybrat]
(gdb) call ((void*(*)(void))history_list)()
$413 = (void *) 0x62222b86fc70
(gdb) print ((void*(*)(void))history_list)()
$414 = (void *) 0x62222b86fc70
$415 = (void *(*)(void)) 0x622312369770 <history_list>
(gdb) call ((void*(*)(void))history_list)
$416 = (void *(*)(void)) 0x622312369770 <history_list>
print 2
call 2 #totéž


A ještě, je mozné toto provést na snapshotu (coredumpu)? tedy za předpokladu, že první krok(volání history_list) nepůjde udělat, ale tu druhou část (když budu znát ten pointer)
« Poslední změna: Dnes v 14:38:53 od Ħαℓ₸℮ℵ ␏⫢ ⦚ »