ایک بار ایک انٹرویو کے دوران مجھ سے پوچھا گیا کہ اگر آپ کو ڈسک میں جگہ ختم ہونے کی وجہ سے کوئی سروس کام نہیں کر رہی تو آپ کیا کریں گے؟
البتہ میں نے جواب دیا کہ میں دیکھوں گا کہ اس جگہ پر کیا قبضہ ہے اور اگر ممکن ہوا تو اس جگہ کو صاف کر دوں گا۔
پھر انٹرویو لینے والے نے پوچھا، اگر پارٹیشن پر خالی جگہ نہ ہو، لیکن آپ کو کوئی فائل بھی نظر نہیں آتی جو ساری جگہ لے لے؟
اس پر میں نے کہا کہ آپ ہمیشہ اوپن فائل ڈسکرپٹرز کو دیکھ سکتے ہیں، مثال کے طور پر lsof کمانڈ کے ساتھ، اور سمجھ سکتے ہیں کہ کونسی ایپلیکیشن نے تمام دستیاب جگہ لی ہے، اور پھر آپ حالات کے مطابق کام کر سکتے ہیں، اس پر منحصر ہے کہ آیا ڈیٹا کی ضرورت ہے۔ .
انٹرویو لینے والے نے مجھے آخری لفظ پر روکا، اپنے سوال میں اضافہ کیا: "فرض کریں کہ ہمیں ڈیٹا کی ضرورت نہیں ہے، یہ صرف ایک ڈیبگ لاگ ہے، لیکن ایپلیکیشن کام نہیں کرتی کیونکہ یہ ڈیبگ نہیں لکھ سکتی"؟
"ٹھیک ہے،" میں نے جواب دیا، "ہم ایپلیکیشن کی تشکیل میں ڈیبگ کو بند کر کے اسے دوبارہ شروع کر سکتے ہیں۔"
انٹرویو لینے والے نے اعتراض کیا: "نہیں، ہم ایپلیکیشن کو دوبارہ شروع نہیں کر سکتے، ہمارے پاس اب بھی اہم ڈیٹا میموری میں محفوظ ہے، اور اہم کلائنٹس خود سروس سے جڑے ہوئے ہیں، جنہیں ہم دوبارہ جوڑنے پر مجبور نہیں کر سکتے۔"
"ٹھیک ہے،" میں نے کہا، "اگر ہم ایپلیکیشن کو دوبارہ شروع نہیں کر سکتے اور ڈیٹا ہمارے لیے اہم نہیں ہے، تو ہم اس کھلی فائل کو فائل ڈسکرپٹر کے ذریعے صاف کر سکتے ہیں، چاہے ہم اسے ls کمانڈ میں نہ دیکھیں۔ فائل سسٹم پر۔"
انٹرویو لینے والا خوش تھا، لیکن میں نہیں تھا۔
پھر میں نے سوچا، میرے علم کی جانچ کرنے والا شخص گہرا کیوں نہیں کرتا؟ لیکن کیا ہوگا اگر ڈیٹا سب کے بعد اہم ہے؟ کیا ہوگا اگر ہم کسی عمل کو دوبارہ شروع نہیں کرسکتے ہیں، اور یہ عمل ایک پارٹیشن پر فائل سسٹم کو لکھتا ہے جس میں خالی جگہ نہیں ہے؟ کیا ہوگا اگر ہم نہ صرف اس ڈیٹا کو کھو سکتے ہیں جو پہلے سے لکھا جا چکا ہے، بلکہ وہ ڈیٹا بھی جسے یہ عمل لکھتا ہے یا لکھنے کی کوشش کرتا ہے؟
تزک
اپنے کیریئر کے شروع میں، میں نے ایک چھوٹی ایپلی کیشن بنانے کی کوشش کی جس میں صارف کی معلومات کو ذخیرہ کرنے کی ضرورت تھی۔ اور پھر میں نے سوچا، میں صارف کو اس کے ڈیٹا سے کیسے ملا سکتا ہوں۔ مثال کے طور پر، میرے پاس Ivanov Ivan Ivanovich ہے، اور اس کے پاس کچھ معلومات ہیں، لیکن میں ان سے دوستی کیسے کر سکتا ہوں؟ میں براہ راست اشارہ کر سکتا ہوں کہ "Tuzik" نامی کتا اسی آئیوان کا ہے۔ لیکن کیا ہوگا اگر وہ اپنا نام بدل لے اور آئیون کی بجائے اولیا بن جائے؟ تب یہ پتہ چلے گا کہ ہمارے اولیا ایوانوانا ایوانوا کے پاس اب کتا نہیں رہے گا، اور ہمارا توزک اب بھی غیر موجود ایوان سے تعلق رکھتا ہے۔ ایک ڈیٹابیس جس نے ہر صارف کو ایک منفرد شناخت کنندہ (ID) دیا اس نے اس مسئلے کو حل کرنے میں مدد کی، اور میرا Tuzik اس ID سے منسلک تھا، جو درحقیقت صرف ایک سیریل نمبر تھا۔ اس طرح، اس کے مالک کے پاس ID نمبر 2 تھا، اور کسی وقت آئیون اس ID کے تحت تھا، اور پھر اولیا اسی ID کے تحت ہو گیا۔ انسانیت اور حیوانات کا مسئلہ عملی طور پر حل ہو گیا۔
فائل ڈسکرپٹر
اس فائل کے ساتھ کام کرنے والے فائل اور پروگرام کا مسئلہ تقریباً ہمارے کتے اور انسان کا مسئلہ ہے۔ فرض کریں کہ میں نے ivan.txt نامی ایک فائل کھولی اور اس میں لفظ tuzik لکھنا شروع کیا، لیکن فائل میں صرف پہلا حرف "t" لکھنے میں کامیاب ہوا، اور اس فائل کا نام کسی نے بدل کر، مثال کے طور پر olya.txt رکھ دیا۔ لیکن فائل وہی ہے، اور میں اب بھی اس میں اپنا اککا ریکارڈ کرنا چاہتا ہوں۔ ہر بار سسٹم کال کے ذریعے فائل کھولی جاتی ہے۔
لینکس میں، libc لائبریری ہر چلنے والی ایپلیکیشن (عمل) کے لیے 3 ڈسکرپٹر فائلیں کھولتی ہے، جن کی تعداد 0,1,2 ہے۔ مزید معلومات لنکس پر مل سکتی ہیں۔
- فائل ڈسکرپٹر 0 کو STDIN کہا جاتا ہے اور یہ ایپلیکیشن ان پٹ سے وابستہ ہے۔
- فائل ڈسکرپٹر 1 کو STDOUT کہا جاتا ہے اور اسے ایپلی کیشنز ڈیٹا آؤٹ پٹ کرنے کے لیے استعمال کرتی ہے، جیسے کہ پرنٹ کمانڈز
- فائل ڈسکرپٹر 2 کو STDERR کہا جاتا ہے اور ایپلیکیشنز کے ذریعے اسے آؤٹ پٹ ایرر میسیجز کے لیے استعمال کیا جاتا ہے۔
اگر آپ اپنے پروگرام میں پڑھنے یا لکھنے کے لیے کوئی فائل کھولتے ہیں تو غالب امکان ہے کہ آپ کو پہلی مفت آئی ڈی ملے گی اور اس کا نمبر 3 ہوگا۔
اگر آپ کو اس کا PID معلوم ہے تو فائل ڈسکرپٹرز کی فہرست کسی بھی عمل کے لیے دیکھی جا سکتی ہے۔
مثال کے طور پر، آئیے bash کنسول کھولیں اور اپنے عمل کی PID کو دیکھیں
[user@localhost ]$ echo $$
15771
دوسرے کنسول میں چلتے ہیں۔
[user@localhost ]$ ls -lah /proc/15771/fd/
total 0
dr-x------ 2 user user 0 Oct 7 15:42 .
dr-xr-xr-x 9 user user 0 Oct 7 15:42 ..
lrwx------ 1 user user 64 Oct 7 15:42 0 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 1 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 2 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 255 -> /dev/pts/21
آپ اس مضمون کے مقاصد کے لیے فائل ڈسکرپٹر نمبر 255 کو محفوظ طریقے سے نظر انداز کر سکتے ہیں؛ اسے اپنی ضروریات کے لیے خود bash کے ذریعے کھولا گیا تھا، نہ کہ منسلک لائبریری کے ذریعے۔
اب تمام 3 ڈسکرپٹر فائلیں سیوڈو ٹرمینل ڈیوائس سے وابستہ ہیں۔
[user@localhost ]$ echo "hello world" > /proc/15771/fd/0
اور پہلے کنسول میں ہم دیکھیں گے۔
[user@localhost ]$ hello world
ری ڈائریکٹ اور پائپ
آپ آسانی سے ان 3 ڈسکرپٹر فائلوں کو کسی بھی عمل میں اوور رائیڈ کر سکتے ہیں، بشمول bash میں، مثال کے طور پر ایک پائپ کے ذریعے جو دو پروسیس کو جوڑتا ہے، دیکھیں
[user@localhost ]$ cat /dev/zero | sleep 10000
آپ اس کمانڈ کو خود چلا سکتے ہیں۔ strace -f اور دیکھیں کہ اندر کیا ہو رہا ہے، لیکن میں آپ کو مختصراً بتاؤں گا۔
PID 15771 کے ساتھ ہمارا پیرنٹ باش عمل ہماری کمانڈ کو پارس کرتا ہے اور بالکل سمجھتا ہے کہ ہم کتنے کمانڈز چلانا چاہتے ہیں، ہمارے معاملے میں ان میں سے دو ہیں: بلی اور نیند۔ Bash جانتا ہے کہ اسے دو چائلڈ پروسیس بنانے، اور انہیں ایک پائپ میں ضم کرنے کی ضرورت ہے۔ مجموعی طور پر، bash کو 2 چائلڈ پروسیس اور ایک پائپ کی ضرورت ہوگی۔
Bash چائلڈ پروسیس بنانے سے پہلے سسٹم کال چلاتا ہے۔
والدین کے عمل کے لیے، ایسا لگتا ہے کہ پہلے سے ہی ایک پائپ موجود ہے، لیکن ابھی تک کوئی چائلڈ پروسیس نہیں ہے:
PID command
15771 bash
lrwx------ 1 user user 64 Oct 7 15:42 0 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 1 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 2 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 3 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct 7 15:42 4 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct 7 15:42 255 -> /dev/pts/21
پھر سسٹم کال کا استعمال کریں۔
PID command
15771 bash
lrwx------ 1 user user 64 Oct 7 15:42 0 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 1 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 2 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 3 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct 7 15:42 4 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct 7 15:42 255 -> /dev/pts/21
PID command
9004 bash
lrwx------ 1 user user 64 Oct 7 15:57 0 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:57 1 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:57 2 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:57 3 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct 7 15:57 4 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct 7 15:57 255 -> /dev/pts/21
PID command
9005 bash
lrwx------ 1 user user 64 Oct 7 15:57 0 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:57 1 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:57 2 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:57 3 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct 7 15:57 4 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct 7 15:57 255 -> /dev/pts/21
یہ نہ بھولیں کہ کلون تمام فائل ڈسکرپٹرز کے ساتھ عمل کو کلون کرتا ہے، اس لیے وہ والدین کے عمل اور بچوں میں ایک جیسے ہوں گے۔ PID 15771 کے ساتھ والدین کے عمل کا کام بچوں کے عمل کی نگرانی کرنا ہے، لہذا یہ صرف بچوں کے جواب کا انتظار کرتا ہے۔
لہذا، اسے پائپ کی ضرورت نہیں ہے، اور یہ 3 اور 4 نمبر والے فائل ڈسکرپٹرز کو بند کر دیتا ہے۔
PID 9004 کے ساتھ پہلے چائلڈ باش کے عمل میں، سسٹم کال کریں۔
PID 9005 کے ساتھ دوسرے چائلڈ پروسیس میں، bash فائل ڈسکرپٹر STDIN نمبر 2 کو تبدیل کرنے کے لیے dup0 کا استعمال کرتا ہے۔ اب PID 9005 کے ساتھ ہمارا دوسرا bash جو بھی پڑھے گا وہ پائپ سے پڑھا جائے گا۔
اس کے بعد، 3 اور 4 نمبر والے فائل ڈسکرپٹرز بھی چائلڈ پروسیس میں بند ہو جاتے ہیں، کیونکہ وہ مزید استعمال نہیں ہوتے۔
میں جان بوجھ کر فائل ڈسکرپٹر 255 کو نظر انداز کرتا ہوں؛ یہ اندرونی مقاصد کے لیے خود bash کے ذریعے استعمال ہوتا ہے اور اسے چائلڈ پروسیس میں بھی بند کر دیا جائے گا۔
اگلا، PID 9004 کے ساتھ پہلے چائلڈ پروسیس میں، bash سسٹم کال کا استعمال شروع کرتا ہے۔
PID 9005 کے ساتھ دوسرے چائلڈ پروسیس میں، bash ہمارے کیس /usr/bin/sleep میں، ہم نے بیان کردہ دوسرا قابل عمل چلاتا ہے۔
ایگزیک سسٹم کال فائل ہینڈلز کو بند نہیں کرتی جب تک کہ اوپن کال کے وقت انہیں O_CLOEXEC پرچم کے ساتھ نہ کھولا گیا ہو۔ ہمارے معاملے میں، قابل عمل فائلوں کو لانچ کرنے کے بعد، تمام موجودہ فائل ڈسکرپٹرز محفوظ ہو جائیں گے۔
کنسول میں چیک کریں:
[user@localhost ]$ pgrep -P 15771
9004
9005
[user@localhost ]$ ls -lah /proc/15771/fd/
total 0
dr-x------ 2 user user 0 Oct 7 15:42 .
dr-xr-xr-x 9 user user 0 Oct 7 15:42 ..
lrwx------ 1 user user 64 Oct 7 15:42 0 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 1 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 2 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 255 -> /dev/pts/21
[user@localhost ]$ ls -lah /proc/9004/fd
total 0
dr-x------ 2 user user 0 Oct 7 15:57 .
dr-xr-xr-x 9 user user 0 Oct 7 15:57 ..
lrwx------ 1 user user 64 Oct 7 15:57 0 -> /dev/pts/21
l-wx------ 1 user user 64 Oct 7 15:57 1 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct 7 15:57 2 -> /dev/pts/21
lr-x------ 1 user user 64 Oct 7 15:57 3 -> /dev/zero
[user@localhost ]$ ls -lah /proc/9005/fd
total 0
dr-x------ 2 user user 0 Oct 7 15:57 .
dr-xr-xr-x 9 user user 0 Oct 7 15:57 ..
lr-x------ 1 user user 64 Oct 7 15:57 0 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct 7 15:57 1 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:57 2 -> /dev/pts/21
[user@localhost ]$ ps -up 9004
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
user 9004 0.0 0.0 107972 620 pts/21 S+ 15:57 0:00 cat /dev/zero
[user@localhost ]$ ps -up 9005
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
user 9005 0.0 0.0 107952 360 pts/21 S+ 15:57 0:00 sleep 10000
جیسا کہ آپ دیکھ سکتے ہیں، ہمارے پائپ کی منفرد تعداد دونوں عملوں میں ایک جیسی ہے۔ اس طرح ہمارا ایک ہی والدین کے ساتھ دو مختلف عملوں کے درمیان تعلق ہے۔
ان لوگوں کے لئے جو سسٹم کالز سے واقف نہیں ہیں جو bash استعمال کرتا ہے، میں اسٹریس کے ذریعے کمانڈز چلانے اور اندرونی طور پر کیا ہو رہا ہے دیکھنے کی سفارش کرتا ہوں، مثال کے طور پر اس طرح:
strace -s 1024 -f bash -c "ls | grep hello"
آئیے کم ڈسک کی جگہ اور عمل کو دوبارہ شروع کیے بغیر ڈیٹا کو بچانے کی کوشش کے ساتھ اپنے مسئلے کی طرف لوٹتے ہیں۔ آئیے ایک چھوٹا سا پروگرام لکھتے ہیں جو ڈسک پر تقریباً 1 میگا بائٹ فی سیکنڈ لکھے گا۔ مزید برآں، اگر کسی وجہ سے ہم ڈسک پر ڈیٹا لکھنے میں ناکام رہے، تو ہم اسے نظر انداز کر دیں گے اور ایک سیکنڈ میں دوبارہ ڈیٹا لکھنے کی کوشش کریں گے۔ مثال میں جو میں Python استعمال کر رہا ہوں، آپ کوئی اور پروگرامنگ زبان استعمال کر سکتے ہیں۔
[user@localhost ]$ cat openforwrite.py
import datetime
import time
mystr="a"*1024*1024+"n"
with open("123.txt", "w") as f:
while True:
try:
f.write(str(datetime.datetime.now()))
f.write(mystr)
f.flush()
time.sleep(1)
except:
pass
آئیے پروگرام چلاتے ہیں اور فائل ڈسکرپٹرز کو دیکھتے ہیں۔
[user@localhost ]$ python openforwrite.py &
[1] 3762
[user@localhost ]$ ps axuf | grep [o]penforwrite
user 3762 0.0 0.0 128600 5744 pts/22 S+ 16:28 0:00 | _ python openforwrite.py
[user@localhost ]$ ls -la /proc/3762/fd
total 0
dr-x------ 2 user user 0 Oct 7 16:29 .
dr-xr-xr-x 9 user user 0 Oct 7 16:29 ..
lrwx------ 1 user user 64 Oct 7 16:29 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 7 16:29 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 7 16:29 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct 7 16:29 3 -> /home/user/123.txt
جیسا کہ آپ دیکھ سکتے ہیں، ہمارے پاس ہمارے 3 معیاری فائل ڈسکرپٹرز ہیں اور ایک اور جسے ہم نے کھولا ہے۔ آئیے فائل کا سائز چیک کریں:
[user@localhost ]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 117M Oct 7 16:30 123.txt
ڈیٹا لکھا جا رہا ہے، ہم فائل پر اجازتیں تبدیل کرنے کی کوشش کرتے ہیں:
[user@localhost ]$ sudo chown root: 123.txt
[user@localhost ]$ ls -lah 123.txt
-rw-rw-r-- 1 root root 168M Oct 7 16:31 123.txt
[user@localhost ]$ ls -lah 123.txt
-rw-rw-r-- 1 root root 172M Oct 7 16:31 123.txt
ہم دیکھتے ہیں کہ ڈیٹا اب بھی لکھا جا رہا ہے، حالانکہ ہمارے صارف کو فائل میں لکھنے کی اجازت نہیں ہے۔ آئیے اسے دور کرنے کی کوشش کریں:
[user@localhost ]$ sudo rm 123.txt
[user@localhost ]$ ls 123.txt
ls: cannot access 123.txt: No such file or directory
ڈیٹا کہاں لکھا ہے؟ اور کیا وہ بالکل لکھے گئے ہیں؟ ہم چیک کرتے ہیں:
[user@localhost ]$ ls -la /proc/3762/fd
total 0
dr-x------ 2 user user 0 Oct 7 16:29 .
dr-xr-xr-x 9 user user 0 Oct 7 16:29 ..
lrwx------ 1 user user 64 Oct 7 16:29 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 7 16:29 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 7 16:29 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct 7 16:29 3 -> /home/user/123.txt (deleted)
ہاں، ہمارا فائل ڈسکرپٹر اب بھی موجود ہے اور ہم اس فائل ڈسکرپٹر کو اپنی پرانی فائل کی طرح دیکھ سکتے ہیں، ہم اسے پڑھ سکتے ہیں، صاف کر سکتے ہیں اور کاپی کر سکتے ہیں۔
آئیے فائل کا سائز دیکھتے ہیں:
[user@localhost ]$ lsof | grep 123.txt
python 31083 user 3w REG 8,5 19923457 2621522 /home/user/123.txt
فائل کا سائز 19923457 ہے۔ آئیے فائل کو صاف کرنے کی کوشش کریں:
[user@localhost ]$ truncate -s 0 /proc/31083/fd/3
[user@localhost ]$ lsof | grep 123.txt
python 31083 user 3w REG 8,5 136318390 2621522 /home/user/123.txt
جیسا کہ آپ دیکھ سکتے ہیں، فائل کا سائز صرف بڑھ رہا ہے اور ہمارے ٹرنک نے کام نہیں کیا۔ آئیے سسٹم کال دستاویزات کو دیکھتے ہیں۔
with open("123.txt", "w") as f:
ہمیں ڈالنا ہے
with open("123.txt", "a") as f:
"w" پرچم کے ساتھ چیک کر رہا ہے۔
[user@localhost ]$ strace -e trace=open python openforwrite.py 2>&1| grep 123.txt
open("123.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
اور "a" پرچم کے ساتھ
[user@localhost ]$ strace -e trace=open python openforwrite.py 2>&1| grep 123.txt
open("123.txt", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3
پہلے سے چلنے والے عمل کو پروگرام کرنا
اکثر پروگرامرز، جب پروگرام بناتے اور جانچتے ہیں، ڈیبگرز (مثال کے طور پر GDB) یا ایپلی کیشن میں لاگنگ کی مختلف سطحوں کا استعمال کرتے ہیں۔ لینکس دراصل پہلے سے چل رہے پروگرام کو لکھنے اور تبدیل کرنے کی صلاحیت فراہم کرتا ہے، مثال کے طور پر متغیرات کی قدروں کو تبدیل کرنا، بریک پوائنٹ سیٹ کرنا، وغیرہ۔
فائل لکھنے کے لیے ڈسک کی کافی جگہ نہ ہونے کے بارے میں اصل سوال کی طرف لوٹتے ہوئے، آئیے اس مسئلے کو حل کرنے کی کوشش کرتے ہیں۔
آئیے اپنے پارٹیشن کے لیے ایک فائل بنائیں، جسے ہم الگ ڈسک کے طور پر نصب کریں گے۔
[user@localhost ~]$ dd if=/dev/zero of=~/tempfile_for_article.dd bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 0.00525929 s, 2.0 GB/s
[user@localhost ~]$
آئیے ایک فائل سسٹم بنائیں:
[user@localhost ~]$ mkfs.ext4 ~/tempfile_for_article.dd
mke2fs 1.42.9 (28-Dec-2013)
/home/user/tempfile_for_article.dd is not a block special device.
Proceed anyway? (y,n) y
...
Writing superblocks and filesystem accounting information: done
[user@localhost ~]$
فائل سسٹم کو ماؤنٹ کریں:
[user@localhost ~]$ sudo mount ~/tempfile_for_article.dd /mnt/
[sudo] password for user:
[user@localhost ~]$ df -h | grep mnt
/dev/loop0 8.7M 172K 7.9M 3% /mnt
ہم اپنے مالک کے ساتھ ایک ڈائریکٹری بناتے ہیں:
[user@localhost ~]$ sudo mkdir /mnt/logs
[user@localhost ~]$ sudo chown user: /mnt/logs
آئیے صرف اپنے پروگرام میں لکھنے کے لیے فائل کھولتے ہیں:
with open("/mnt/logs/123.txt", "w") as f:
لانچ
[user@localhost ]$ python openforwrite.py
ہم چند سیکنڈ انتظار کرتے ہیں۔
[user@localhost ~]$ df -h | grep mnt
/dev/loop0 8.7M 8.0M 0 100% /mnt
لہذا، ہمارے پاس اس مضمون کے شروع میں بیان کردہ مسئلہ ہے۔ خالی جگہ 0، 100% پر قبضہ کر لیا گیا۔
ہمیں یاد ہے کہ کام کی شرائط کے مطابق، ہم بہت اہم ڈیٹا ریکارڈ کرنے کی کوشش کر رہے ہیں جو ضائع نہیں ہو سکتا۔ اور اسی وقت، ہمیں عمل کو دوبارہ شروع کیے بغیر سروس کو ٹھیک کرنے کی ضرورت ہے۔
ہم کہتے ہیں کہ ہمارے پاس ابھی بھی ڈسک کی جگہ ہے، لیکن ایک مختلف پارٹیشن میں، مثال کے طور پر /home میں۔
آئیے اپنے کوڈ کو "مکھی پر دوبارہ پروگرام" کرنے کی کوشش کریں۔
آئیے اپنے عمل کے پی آئی ڈی کو دیکھتے ہیں، جس نے ڈسک کی تمام جگہ کھا لی ہے۔
[user@localhost ~]$ ps axuf | grep [o]penfor
user 10078 27.2 0.0 128600 5744 pts/22 R+ 11:06 0:02 | _ python openforwrite.py
gdb کے ذریعے عمل سے جڑیں۔
[user@localhost ~]$ gdb -p 10078
...
(gdb)
آئیے اوپن فائل ڈسکرپٹرز کو دیکھتے ہیں:
(gdb) shell ls -lah /proc/10078/fd/
total 0
dr-x------ 2 user user 0 Oct 8 11:06 .
dr-xr-xr-x 9 user user 0 Oct 8 11:06 ..
lrwx------ 1 user user 64 Oct 8 11:09 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:09 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:06 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct 8 11:09 3 -> /mnt/logs/123.txt
ہم فائل ڈسکرپٹر نمبر 3 کے بارے میں معلومات کو دیکھتے ہیں، جس میں ہماری دلچسپی ہے۔
(gdb) shell cat /proc/10078/fdinfo/3
pos: 8189952
flags: 0100001
mnt_id: 482
اس بات کو ذہن میں رکھتے ہوئے کہ Python کیا سسٹم کال کرتا ہے (اوپر دیکھیں کہ ہم نے اسٹریس کہاں سے چلائی اور اوپن کال کہاں ملی)، فائل کو کھولنے کے لیے اپنے کوڈ پر کارروائی کرتے وقت، ہم اپنے عمل کی جانب سے خود بھی ایسا ہی کرتے ہیں، لیکن ہمیں O_WRONLY|O_CREAT| O_TRUNC بٹس عددی قدر سے بدلتے ہیں۔ ایسا کرنے کے لیے، مثال کے طور پر دانا کے ذرائع کھولیں۔
#O_WRONLY 00000001 کی وضاحت کریں۔
#O_CREAT 00000100 کی وضاحت کریں۔
#O_TRUNC 00001000 کی وضاحت کریں۔
ہم تمام اقدار کو یکجا کرتے ہیں، ہمیں 00001101 ملتا ہے۔
ہم اپنی کال کو جی ڈی بی سے چلاتے ہیں۔
(gdb) call open("/home/user/123.txt", 00001101,0666)
$1 = 4
لہذا ہمیں نمبر 4 کے ساتھ ایک نیا فائل ڈسکرپٹر اور ایک اور پارٹیشن پر ایک نئی اوپن فائل ملی، ہم چیک کرتے ہیں:
(gdb) shell ls -lah /proc/10078/fd/
total 0
dr-x------ 2 user user 0 Oct 8 11:06 .
dr-xr-xr-x 9 user user 0 Oct 8 11:06 ..
lrwx------ 1 user user 64 Oct 8 11:09 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:09 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:06 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct 8 11:09 3 -> /mnt/logs/123.txt
l-wx------ 1 user user 64 Oct 8 11:15 4 -> /home/user/123.txt
ہمیں پائپ کے ساتھ مثال یاد ہے - کس طرح bash فائل ڈسکرپٹرز کو تبدیل کرتا ہے، اور ہم پہلے ہی dup2 سسٹم کال سیکھ چکے ہیں۔
ہم ایک فائل ڈسکرپٹر کو دوسرے سے تبدیل کرنے کی کوشش کرتے ہیں۔
(gdb) call dup2(4,3)
$2 = 3
جانچ پڑتال:
(gdb) shell ls -lah /proc/10078/fd/
total 0
dr-x------ 2 user user 0 Oct 8 11:06 .
dr-xr-xr-x 9 user user 0 Oct 8 11:06 ..
lrwx------ 1 user user 64 Oct 8 11:09 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:09 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:06 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct 8 11:09 3 -> /home/user/123.txt
l-wx------ 1 user user 64 Oct 8 11:15 4 -> /home/user/123.txt
ہم فائل ڈسکرپٹر 4 کو بند کرتے ہیں، کیونکہ ہمیں اس کی ضرورت نہیں ہے:
(gdb) call close (4)
$1 = 0
اور جی ڈی بی سے باہر نکلیں۔
(gdb) quit
A debugging session is active.
Inferior 1 [process 10078] will be detached.
Quit anyway? (y or n) y
Detaching from program: /usr/bin/python2.7, process 10078
نئی فائل کی جانچ پڑتال:
[user@localhost ~]$ ls -lah /home/user/123.txt
-rw-rw-r-- 1 user user 5.1M Oct 8 11:18 /home/user/123.txt
[user@localhost ~]$ ls -lah /home/user/123.txt
-rw-rw-r-- 1 user user 7.1M Oct 8 11:18 /home/user/123.txt
جیسا کہ آپ دیکھ سکتے ہیں، ڈیٹا کو ایک نئی فائل میں لکھا گیا ہے، آئیے پرانی فائل کو چیک کریں:
[user@localhost ~]$ ls -lah /mnt/logs/123.txt
-rw-rw-r-- 1 user user 7.9M Oct 8 11:08 /mnt/logs/123.txt
کوئی ڈیٹا ضائع نہیں ہوتا، ایپلیکیشن کام کرتی ہے، نوشتہ جات نئے مقام پر لکھے جاتے ہیں۔
آئیے کام کو تھوڑا سا پیچیدہ کریں۔
آئیے تصور کریں کہ ڈیٹا ہمارے لیے اہم ہے، لیکن ہمارے پاس کسی بھی پارٹیشن میں ڈسک کی جگہ نہیں ہے اور ہم ڈسک کو جوڑ نہیں سکتے۔
ہم جو کر سکتے ہیں وہ یہ ہے کہ اپنے ڈیٹا کو کہیں ری ڈائریکٹ کریں، مثال کے طور پر پائپ پر، اور بدلے میں کسی پروگرام کے ذریعے ڈیٹا کو پائپ سے نیٹ ورک پر ری ڈائریکٹ کریں، مثال کے طور پر نیٹ کیٹ۔
ہم mkfifo کمانڈ کے ساتھ ایک نامی پائپ بنا سکتے ہیں۔ یہ فائل سسٹم پر ایک چھدم فائل بنائے گا چاہے اس پر کوئی خالی جگہ نہ ہو۔
درخواست کو دوبارہ شروع کریں اور چیک کریں:
[user@localhost ]$ python openforwrite.py
[user@localhost ~]$ ps axuf | grep [o]pen
user 5946 72.9 0.0 128600 5744 pts/22 R+ 11:27 0:20 | _ python openforwrite.py
[user@localhost ~]$ ls -lah /proc/5946/fd
total 0
dr-x------ 2 user user 0 Oct 8 11:27 .
dr-xr-xr-x 9 user user 0 Oct 8 11:27 ..
lrwx------ 1 user user 64 Oct 8 11:28 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:28 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:27 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct 8 11:28 3 -> /mnt/logs/123.txt
[user@localhost ~]$ df -h | grep mnt
/dev/loop0 8.7M 8.0M 0 100% /mnt
ڈسک کی کوئی جگہ نہیں ہے، لیکن ہم وہاں کامیابی کے ساتھ ایک نامی پائپ بناتے ہیں:
[user@localhost ~]$ mkfifo /mnt/logs/megapipe
[user@localhost ~]$ ls -lah /mnt/logs/megapipe
prw-rw-r-- 1 user user 0 Oct 8 11:28 /mnt/logs/megapipe
اب ہمیں کسی نہ کسی طرح اس پائپ میں جانے والے تمام ڈیٹا کو نیٹ ورک کے ذریعے دوسرے سرور پر لپیٹنا ہوگا؛ وہی نیٹ کیٹ اس کے لیے موزوں ہے۔
سرور remote-server.example.com پر ہم چلاتے ہیں۔
[user@localhost ~]$ nc -l 7777 > 123.txt
اپنے پریشانی والے سرور پر ہم ایک الگ ٹرمینل میں لانچ کرتے ہیں۔
[user@localhost ~]$ nc remote-server.example.com 7777 < /mnt/logs/megapipe
اب پائپ میں ختم ہونے والا تمام ڈیٹا خود بخود netcat میں stdin میں چلا جائے گا، جو اسے پورٹ 7777 پر نیٹ ورک کو بھیج دے گا۔
ہمیں بس اپنا ڈیٹا اس نامی پائپ میں لکھنا شروع کرنا ہے۔
ہمارے پاس پہلے سے ہی ایپلیکیشن چل رہی ہے:
[user@localhost ~]$ ps axuf | grep [o]pen
user 5946 99.8 0.0 128600 5744 pts/22 R+ 11:27 169:27 | _ python openforwrite.py
[user@localhost ~]$ ls -lah /proc/5946/fd
total 0
dr-x------ 2 user user 0 Oct 8 11:27 .
dr-xr-xr-x 9 user user 0 Oct 8 11:27 ..
lrwx------ 1 user user 64 Oct 8 11:28 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:28 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:27 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct 8 11:28 3 -> /mnt/logs/123.txt
تمام جھنڈوں میں سے، ہمیں صرف O_WRONLY کی ضرورت ہے کیونکہ فائل پہلے سے موجود ہے اور ہمیں اسے صاف کرنے کی ضرورت نہیں ہے
[user@localhost ~]$ gdb -p 5946
...
(gdb) call open("/mnt/logs/megapipe", 00000001,0666)
$1 = 4
(gdb) shell ls -lah /proc/5946/fd
total 0
dr-x------ 2 user user 0 Oct 8 11:27 .
dr-xr-xr-x 9 user user 0 Oct 8 11:27 ..
lrwx------ 1 user user 64 Oct 8 11:28 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:28 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:27 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct 8 11:28 3 -> /mnt/logs/123.txt
l-wx------ 1 user user 64 Oct 8 14:20 4 -> /mnt/logs/megapipe
(gdb) call dup2(4,3)
$2 = 3
(gdb) shell ls -lah /proc/5946/fd
total 0
dr-x------ 2 user user 0 Oct 8 11:27 .
dr-xr-xr-x 9 user user 0 Oct 8 11:27 ..
lrwx------ 1 user user 64 Oct 8 11:28 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:28 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:27 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct 8 11:28 3 -> /mnt/logs/megapipe
l-wx------ 1 user user 64 Oct 8 14:20 4 -> /mnt/logs/megapipe
(gdb) call close(4)
$3 = 0
(gdb) shell ls -lah /proc/5946/fd
total 0
dr-x------ 2 user user 0 Oct 8 11:27 .
dr-xr-xr-x 9 user user 0 Oct 8 11:27 ..
lrwx------ 1 user user 64 Oct 8 11:28 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:28 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:27 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct 8 11:28 3 -> /mnt/logs/megapipe
(gdb) quit
A debugging session is active.
Inferior 1 [process 5946] will be detached.
Quit anyway? (y or n) y
Detaching from program: /usr/bin/python2.7, process 5946
ریموٹ سرور remote-server.example.com کو چیک کر رہا ہے۔
[user@localhost ~]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 38M Oct 8 14:21 123.txt
ڈیٹا آرہا ہے، ہم مسئلہ سرور کو چیک کرتے ہیں۔
[user@localhost ~]$ ls -lah /mnt/logs/
total 7.9M
drwxr-xr-x 2 user user 1.0K Oct 8 11:28 .
drwxr-xr-x 4 root root 1.0K Oct 8 10:55 ..
-rw-rw-r-- 1 user user 7.9M Oct 8 14:17 123.txt
prw-rw-r-- 1 user user 0 Oct 8 14:22 megapipe
ڈیٹا محفوظ ہو گیا، مسئلہ حل ہو گیا۔
میں ڈیگیرو سے اپنے ساتھیوں کو ہیلو کہنے کا یہ موقع لیتا ہوں۔
ریڈیو-T پوڈکاسٹ سنیں۔
سب اچھا.
ہوم ورک کے طور پر، میرا مشورہ ہے کہ آپ اس بارے میں سوچیں کہ اگر آپ مندرجہ ذیل کمانڈ کو چلاتے ہیں تو پروسیس فائل ڈسکرپٹرز cat and sleep میں کیا ہوگا:
[user@localhost ~]$ cat /dev/zero 2>/dev/null| sleep 10000
ماخذ: www.habr.com