यदि कोई फ़ाइल हटा दी गई है, लेकिन अभी भी खुली है, तो इसका मतलब है कि फ़ाइल अभी भी फ़ाइल सिस्टम में मौजूद है (इसमें एक इनोड है ), लेकिन इसकी हार्ड लिंक संख्या 0. है। चूंकि फ़ाइल का कोई लिंक नहीं है, आप इसे नाम से नहीं खोल सकते। । किसी फाइल को इनोड द्वारा खोलने की सुविधा नहीं है।
इसके फाइलसिस्टम के माध्यम से फ़ाइल को खोजने का कोई तरीका नहीं है, और विशेष रूप से निर्देशिका में फ़ाइल की तलाश करने का कोई तरीका नहीं है जहां यह अंतिम था। निर्देशिका प्रविष्टि चली गई है। वह सब कुछ फ़ाइल ही रहता है। आप फ़ाइल सिस्टम डीबगर के साथ फ़ाइल पर जा सकते हैं, लेकिन इसके लिए रूट अनुमतियों की आवश्यकता होती है और इसका उपयोग करना कठिन है और त्रुटि-प्रवण है।
लिनक्स के तहत विशेष प्रतीकात्मक लिंक के माध्यम से खुली फाइलों को उजागर करता है /proc
। इन लिंक को कहा जाता है /proc/12345/fd/42
जहां 12345 एक प्रक्रिया का PID है और 42 उस प्रक्रिया में एक फ़ाइल विवरणक की संख्या है। उस प्रक्रिया के समान उपयोगकर्ता के रूप में चलने वाला प्रोग्राम फ़ाइल तक पहुंच सकता है (पढ़ने / लिखने / निष्पादित करने की अनुमति वही है जो आपके पास तब थी जब फ़ाइल हटा दी गई थी)।
वह नाम जिसके तहत फ़ाइल खोली गई थी, अभी भी प्रतीकात्मक लिंक के लक्ष्य में दिखाई दे रही है: यदि फ़ाइल थी /var/log/apache/foo.log
, तो लिंक का लक्ष्य है /var/log/apache/foo.log (deleted)
। (यदि फ़ाइल को खोलने के बाद नाम बदल दिया गया था, तो सिमलिंक का लक्ष्य नाम बदलने को प्रतिबिंबित कर सकता है।)
इस प्रकार आप एक खुली हटाए गए फ़ाइल की सामग्री को पुनर्प्राप्त कर सकते हैं जिसे एक प्रक्रिया की PID दी गई है जो कि खुली है और यह इस तरह से खोली गई डिस्क्रिप्टर है:
recover_open_deleted_file () {
old_name=$(readlink "$1")
case "$old_name" in
*' (deleted)')
old_name=${old_name%' (deleted)'}
if [ -e "$old_name" ]; then
new_name=$(TMPDIR=${old_name%/*} mktemp)
echo "$oldname has been replaced, recovering content to $new_name"
else
new_name="$old_name"
fi
cat <"$1" >"$new_name";;
*) echo "File is not deleted, doing nothing";;
esac
}
recover_open_deleted_file "/proc/$pid/fd/$fd"
यदि आपको केवल प्रक्रिया आईडी पता है, लेकिन विवरणक नहीं है, तो आप सभी फ़ाइलों को पुनर्प्राप्त कर सकते हैं
for x in /proc/$pid/fd/*; do
recover_open_deleted_file "$x"
done
यदि आपको प्रक्रिया आईडी नहीं पता है, तो आप सभी प्रक्रियाओं के बीच खोज कर सकते हैं:
for x in /proc/[1-9]*/fd/*; do
case $(readlink "$x") in
/var/log/apache/*) recover_open_deleted_file "$x";;
esac
done
आप इस सूची को आउटपुट के पार्स करके भी प्राप्त कर सकते हैं lsof
, लेकिन यह अधिक सरल या अधिक विश्वसनीय नहीं है और न ही अधिक पोर्टेबल (यह लिनक्स-विशिष्ट किसी भी तरह है)।
lsof / | awk '(/deleted/||/abc.txt/) {print "FD :-",$4,"| File Name:-",$9}'