Zachránit smazaný soubor či poškozený disk „holýma rukama“
Pohledem do /etc/fstab
můžete zjistit systémovou cestu k zařízení disku, tj. k disku jako takovému. Např. mé USB disky se mountují do adresáře /mnt/usbdisk
, takže vidím, že k disk jako celek je reprezentován „souborem“ /dev/sda1
:
cat /etc/fstab | grep usbdisk # vypíše dejme tomu: # /dev/sda1 /mnt/usbdisk auto noauto,user,rw 0 0
Hardwarově poškozené médium, kde hrozí, že si obsah přečtete jen jednou, je dobré napřed celé zkopírovat do souboru. dd
je program pro podobné tupé kopírování (pro čtení „souboru disku“, potřebujete práva superuživatele, proto „sudo“):
sudo dd if=/dev/sda1 of=~/zachr_flash.img
Dál už vás jistě napadne, že soubor ~/zachr_flash.img
můžete prohledávat. Prohledávat ale lze i přímo disk:
sudo grep -a známý_text_ze_smazaného_souboru /dev/hda1
Parametr -a
grep přinutí pracovat s daty jako s textem, parametr -C
můžete užít k udání počtu vypisovaných řádek před a za nalezeným textem.
Zajímavé výseky či celý disk můžete i prohlížet ve svém oblíbeném editoru, pokud ten objem unese.
Pro dešifrování informaci o souborech či adresářích se hodí hexdump
:
hexdump /dev/sda1 | less
Samozřejmě se v datech ručně vyznáte jen u jednoduchých filesystémů jako FAT a neocenitelný bude jejich popis, pokud se vám jej podaří vygooglit. (Filesystém můžete poznat buď z /etc/fstab
nebo /etc/mtab
, pokud je disk připojen.)
Dolování řetězců
Pokud nevíte, co přesně v binárním souboru hledáte, ale víte, že hledáte text (např. přesný název proměnné prostředí, kterou máte nastavit, ale někdo ji zapomněl zdokumentovat), hodí se nástroj „strings“:
strings /bin/ls | grep -v [a-z] # předpokládejme, že proměnné prostředí neobsahují malá písmenka # a hle: LS_COLORS či COLUMNS je to, co nás možná zajímalo
Změna kódování souborů
Standardem pro převod mezi různými kódováními textových souborů je dnes iconv:
iconv -f iso-8859-2 -t utf8 < vstup > výstup
Je důležité uvědomit si, že převod může selhat, pokud byste převáděli znak, který v cílovém kódování neexistuje. iconv na tohle reaguje správně: přestane převádět a ohlásí „illegal input sequence at position 11“. Pozice je udána počtem znaků, nikoli počtem řádek. Abyste zjistili, na které řádce problém nastal, spusťte „ wc -l
“ na (neúplný) výstup z iconvu.
Málo se ví o tom, že iconv umí nevyjádřitelné znaky ztrátově nahradit a neselhávat. Dokument tím samozřejmě poškodíte (typicky se místo nějakého písmene objeví otazník), ale někdy vám to nemusí vadit. Pro převod se ztrátovým nahrazováním přidejte řetězec „ //TRANSLIT
“ za název cílového kódování:
echo "háčky" | iconv -f utf8 -t ascii//TRANSLIT # vypíše: h??ky
Alternativou k iconv
může být např. recode
, s nějakou jeho pradávnou verzí jsem ale měl špatnou zkušenost: část souboru přeskočil (nezapsal konec) a také nevaroval, že převod není možno uskutečnit. To je zvlášť v případě velkých souborů, které už po sobě nečtete, velký problém.
Když program neřekne, co hledá
Komplexní programy spoléhají na řadu proměnných prostředí, sdílených knihoven, datových souborů. Když je nenajdou, neběží, ale možná neřeknou jasně, kde soubor hledaly.
Přehled všech dynamicky připojovaných knihoven, které program potřebuje, získáte pomocí ldd
:
ldd /usr/bin/perl # vypíše např. # libperl.so => /usr/lib/perl5/5.8.6/i386-linux-thread-multi/CORE/libperl.so (0x0070f000) # libresolv.so.2 => /lib/libresolv.so.2 (0x00625000) # libnsl.so.1 => /lib/libnsl.so.1 (0x00326000) # ...
Ještě obecnější ale je sledovat podrobný výpis všech systémových volání. Tím zjistíte, co všechno se program doopravdy snaží otevřít:
strace perl 2> perl.strace-log # v logu pak najdete, jak perl hledal libperl.so, až ji konečně našel: # open("/usr/lib/perl5/5.8.6/i386-linux-thread-multi/CORE/i686/sse2/libperl.so", O_RDONLY) = -1 ENOENT (No such file or directory) # open("/usr/lib/perl5/5.8.6/i386-linux-thread-multi/CORE/i686/libperl.so", O_RDONLY) = -1 ENOENT (No such file or directory) # open("/usr/lib/perl5/5.8.6/i386-linux-thread-multi/CORE/sse2/libperl.so", O_RDONLY) = -1 ENOENT (No such file or directory) # open("/usr/lib/perl5/5.8.6/i386-linux-thread-multi/CORE/libperl.so", O_RDONLY) = 3 # read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\240\7s"..., 512) = 512
strace
se také hodí, pokud program „záhadně zadrhává“. Může se totiž ukázat, že se například snaží číst z aktuálně nedosažitelného síťového disku.
Které soubory jsou právě otevřeny? Kdo používá soubor?
Pokud jste superuživatel, program lsof
vám vypíše seznam všech otevřených či namapovaných souborů, otevřených síťových spojení i aktuálních adresářů jednotlivých programů:
sudo /usr/sbin/lsof | less -S # a dostanete výpis jako např. tento: # vim 1777 obo cwd DIR 3,3 16384 1 /win # vim 1777 obo txt REG 3,5 2333416 1129997 /usr/bin/vim # vim 1777 obo mem REG 3,5 19668 1211717 /usr/lib/libgpm.so.1.19.0 # ... # vim 1777 obo 5u REG 3,3 12288 1366 /win/.mail.txt.swp # ... # ssh 12134 obo 3u IPv4 247328 TCP 10.10.1.56:42015->pocitac.nekde.cz:ssh (ESTABLISHED)
A pokud se vám například nedaří odpojit disk, protože ho někdo používá (umount: /mnt/cdrom: device is busy), takto zjistíte ID procesů:
sudo /sbin/fuser /mnt/cdrom
Pak už bude stačit „ ps aux | grep ...
“ a buď příslušný program skončíte slušně, nebo ho prostě sestřelíte.