ఒకసారి, ఒక ఇంటర్వ్యూలో, నన్ను అడిగారు, డిస్క్ ఖాళీ అయిపోవడంతో సేవ పని చేయకపోతే మీరు ఏమి చేస్తారు?
అయితే, ఈ స్థలం ఏమి ఆక్రమించబడిందో నేను చూస్తాను మరియు వీలైతే, నేను స్థలాన్ని శుభ్రం చేస్తానని బదులిచ్చాను.
అప్పుడు ఇంటర్వ్యూయర్ అడిగాడు, విభజనపై ఖాళీ స్థలం లేకుంటే ఏమి చేయాలి, అయితే మొత్తం స్థలాన్ని ఆక్రమించే ఫైల్లు కూడా మీకు కనిపించలేదా?
దీనికి నేను మీరు ఎల్లప్పుడూ ఓపెన్ ఫైల్ డిస్క్రిప్టర్లను చూడవచ్చు, ఉదాహరణకు lsof కమాండ్తో, మరియు అందుబాటులో ఉన్న మొత్తం స్థలాన్ని ఏ అప్లికేషన్ తీసుకుందో అర్థం చేసుకోండి, ఆపై డేటా అవసరమా అనే దానిపై ఆధారపడి మీరు పరిస్థితులకు అనుగుణంగా పని చేయవచ్చు. .
ఇంటర్వ్యూయర్ చివరి మాటలో నాకు అంతరాయం కలిగించాడు, అతని ప్రశ్నకు జోడించాడు: "మాకు డేటా అవసరం లేదని అనుకుందాం, ఇది కేవలం డీబగ్ లాగ్ మాత్రమే, కానీ అది డీబగ్ వ్రాయలేనందున అప్లికేషన్ పనిచేయదు"?
“సరే,” నేను బదులిచ్చాను, “మేము అప్లికేషన్ కాన్ఫిగరేషన్లో డీబగ్ని ఆఫ్ చేసి, దాన్ని రీస్టార్ట్ చేయవచ్చు.”
ఇంటర్వ్యూయర్ అభ్యంతరం వ్యక్తం చేశారు: "లేదు, మేము అప్లికేషన్ను పునఃప్రారంభించలేము, మేము ఇప్పటికీ మెమరీలో ముఖ్యమైన డేటాను కలిగి ఉన్నాము మరియు ముఖ్యమైన క్లయింట్లు సేవకు కనెక్ట్ చేయబడ్డారు, మేము మళ్లీ మళ్లీ కనెక్ట్ చేయమని బలవంతం చేయలేము."
“సరే,” నేను అన్నాను, “మనం అప్లికేషన్ను రీస్టార్ట్ చేయలేకపోతే మరియు డేటా మనకు ముఖ్యమైనది కాకపోతే, మనం ఈ ఓపెన్ ఫైల్ను ls కమాండ్లో చూడకపోయినా ఫైల్ డిస్క్రిప్టర్ ద్వారా క్లియర్ చేయవచ్చు. ఫైల్ సిస్టమ్పై."
ఇంటర్వ్యూయర్ సంతోషించారు, కానీ నేను సంతోషించలేదు.
అప్పుడు నేను అనుకున్నాను, నా జ్ఞానాన్ని పరీక్షించే వ్యక్తి ఎందుకు లోతుగా త్రవ్వడు? అయితే డేటా ముఖ్యమైనది అయితే? మనం ప్రాసెస్ను పునఃప్రారంభించలేకపోతే, మరియు ప్రక్రియ ఖాళీ స్థలం లేని విభజనపై ఫైల్ సిస్టమ్కు వ్రాస్తే? మేము ఇప్పటికే వ్రాసిన డేటాను మాత్రమే కాకుండా, ఈ ప్రక్రియ వ్రాసే లేదా వ్రాయడానికి ప్రయత్నించే డేటాను కూడా కోల్పోలేకపోతే?
తుజిక్
నా కెరీర్ ప్రారంభంలో, నేను వినియోగదారు సమాచారాన్ని నిల్వ చేయడానికి అవసరమైన చిన్న అప్లికేషన్ను రూపొందించడానికి ప్రయత్నించాను. ఆపై నేను ఆలోచించాను, నేను వినియోగదారుని అతని డేటాతో ఎలా సరిపోల్చగలను. ఉదాహరణకు, నాకు ఇవనోవ్ ఇవాన్ ఇవనోవిచ్ ఉంది, మరియు అతని వద్ద కొంత సమాచారం ఉంది, కానీ నేను వారితో ఎలా స్నేహం చేయగలను? "తుజిక్" అనే కుక్క ఈ ఇవాన్కు చెందినదని నేను నేరుగా సూచించగలను. కానీ అతను తన పేరును మార్చుకుంటే మరియు ఇవాన్ బదులుగా, ఉదాహరణకు, ఒలియా అవుతాడు? అప్పుడు మా ఒలియా ఇవనోవ్నా ఇవనోవాకు ఇకపై కుక్క ఉండదు, మరియు మా తుజిక్ ఇప్పటికీ ఉనికిలో లేని ఇవాన్కు చెందినవాడు. ప్రతి వినియోగదారుకు ఒక ప్రత్యేక ఐడెంటిఫైయర్ (ID)ని అందించిన డేటాబేస్ ఈ సమస్యను పరిష్కరించడంలో సహాయపడింది మరియు నా Tuzik ఈ IDతో ముడిపడి ఉంది, వాస్తవానికి ఇది కేవలం క్రమ సంఖ్య మాత్రమే. ఆ విధంగా, ఏస్ యజమానికి ID నంబర్ 2 ఉంది మరియు ఏదో ఒక సమయంలో ఇవాన్ ఈ ID కింద ఉన్నాడు, ఆపై ఒలియా అదే ID కింద మారింది. మానవత్వం మరియు పశుపోషణ సమస్య ఆచరణాత్మకంగా పరిష్కరించబడింది.
ఫైల్ డిస్క్రిప్టర్
ఈ ఫైల్తో పనిచేసే ఫైల్ మరియు ప్రోగ్రామ్ యొక్క సమస్య దాదాపుగా మన కుక్క మరియు మనిషికి సంబంధించినది. నేను ivan.txt అనే ఫైల్ను తెరిచి, దానిలో tuzik అనే పదాన్ని రాయడం ప్రారంభించాను, కానీ ఫైల్లో మొదటి అక్షరం “t” మాత్రమే వ్రాయగలిగాను మరియు ఈ ఫైల్ని ఎవరో పేరు మార్చారు, ఉదాహరణకు, olya.txt. కానీ ఫైల్ అలాగే ఉంది మరియు నేను ఇప్పటికీ అందులో నా ఏస్ను రికార్డ్ చేయాలనుకుంటున్నాను. సిస్టమ్ కాల్ ద్వారా ఫైల్ తెరవబడిన ప్రతిసారీ
Linuxలో, libc లైబ్రరీ 3 సంఖ్యతో నడుస్తున్న ప్రతి అప్లికేషన్ (ప్రాసెస్) కోసం 0,1,2 డిస్క్రిప్టర్ ఫైల్లను తెరుస్తుంది. మరింత సమాచారం లింక్లలో చూడవచ్చు
- ఫైల్ డిస్క్రిప్టర్ 0ని STDIN అంటారు మరియు అప్లికేషన్ ఇన్పుట్తో అనుబంధించబడింది
- ఫైల్ డిస్క్రిప్టర్ 1ని STDOUT అని పిలుస్తారు మరియు ప్రింట్ కమాండ్ల వంటి డేటాను అవుట్పుట్ చేయడానికి అప్లికేషన్లు ఉపయోగిస్తాయి
- ఫైల్ డిస్క్రిప్టర్ 2ని STDERR అని పిలుస్తారు మరియు దోష సందేశాలను అవుట్పుట్ చేయడానికి అప్లికేషన్లు ఉపయోగిస్తాయి.
మీ ప్రోగ్రామ్లో మీరు చదవడానికి లేదా వ్రాయడానికి ఏదైనా ఫైల్ను తెరిస్తే, మీరు మొదటి ఉచిత IDని పొందుతారు మరియు అది నంబర్ 3 అవుతుంది.
ఫైల్ డిస్క్రిప్టర్ల జాబితా మీకు దాని PID తెలిస్తే ఏదైనా ప్రక్రియ కోసం చూడవచ్చు.
ఉదాహరణకు, బాష్ కన్సోల్ని తెరిచి, మన ప్రక్రియ యొక్క 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ని సురక్షితంగా విస్మరించవచ్చు; ఇది దాని అవసరాల కోసం బాష్ ద్వారా తెరవబడింది మరియు లింక్ చేయబడిన లైబ్రరీ ద్వారా కాదు.
ఇప్పుడు మొత్తం 3 డిస్క్రిప్టర్ ఫైల్లు సూడో టెర్మినల్ పరికరంతో అనుబంధించబడ్డాయి
[user@localhost ]$ echo "hello world" > /proc/15771/fd/0
మరియు మొదటి కన్సోల్లో మనం చూస్తాము
[user@localhost ]$ hello world
దారి మళ్లింపు మరియు పైప్
మీరు ఈ 3 డిస్క్రిప్టర్ ఫైల్లను బాష్తో సహా ఏదైనా ప్రక్రియలో సులభంగా భర్తీ చేయవచ్చు, ఉదాహరణకు రెండు ప్రక్రియలను అనుసంధానించే పైప్ ద్వారా, చూడండి
[user@localhost ]$ cat /dev/zero | sleep 10000
మీరు ఈ ఆదేశాన్ని మీరే అమలు చేయవచ్చు strace -f మరియు లోపల ఏమి జరుగుతుందో చూడండి, కానీ నేను మీకు క్లుప్తంగా చెబుతాను.
PID 15771తో మా పేరెంట్ బాష్ ప్రాసెస్ మా ఆదేశాన్ని అన్వయిస్తుంది మరియు మనం ఎన్ని కమాండ్లను అమలు చేయాలనుకుంటున్నామో ఖచ్చితంగా అర్థం చేసుకుంటుంది, మా విషయంలో వాటిలో రెండు ఉన్నాయి: పిల్లి మరియు నిద్ర. రెండు చైల్డ్ ప్రాసెస్లను సృష్టించి, వాటిని ఒక పైపులో విలీనం చేయాలని బాష్కు తెలుసు. మొత్తంగా, బాష్కు 2 చైల్డ్ ప్రాసెస్లు మరియు ఒక పైపు అవసరం.
చైల్డ్ ప్రాసెస్లను సృష్టించే ముందు బాష్ సిస్టమ్ కాల్ని అమలు చేస్తుంది
పేరెంట్ ప్రాసెస్ కోసం, ఇప్పటికే పైప్ ఉన్నట్లు కనిపిస్తోంది, కానీ ఇంకా చైల్డ్ ప్రాసెస్లు లేవు:
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తో రెండవ చైల్డ్ ప్రాసెస్లో, ఫైల్ డిస్క్రిప్టర్ STDIN నంబర్ 2ని మార్చడానికి bash dup0ని ఉపయోగిస్తుంది. ఇప్పుడు PID 9005తో మన రెండవ బాష్ చదివే ప్రతిదీ పైప్ నుండి చదవబడుతుంది.
దీని తర్వాత, 3 మరియు 4 నంబర్ గల ఫైల్ డిస్క్రిప్టర్లు కూడా చైల్డ్ ప్రాసెస్లలో మూసివేయబడతాయి, ఎందుకంటే అవి ఇకపై ఉపయోగించబడవు.
నేను ఫైల్ డిస్క్రిప్టర్ 255ని ఉద్దేశపూర్వకంగా విస్మరిస్తాను; ఇది బాష్ ద్వారా అంతర్గత ప్రయోజనాల కోసం ఉపయోగించబడుతుంది మరియు చైల్డ్ ప్రాసెస్లలో కూడా మూసివేయబడుతుంది.
తర్వాత, PID 9004తో మొదటి చైల్డ్ ప్రాసెస్లో, బాష్ సిస్టమ్ కాల్ని ఉపయోగించడం ప్రారంభిస్తుంది
PID 9005తో రెండవ చైల్డ్ ప్రాసెస్లో, మా సందర్భంలో /usr/bin/sleepలో మేము పేర్కొన్న రెండవ ఎక్జిక్యూటబుల్ను bash అమలు చేస్తుంది.
ఓపెన్ కాల్ చేసిన సమయంలో O_CLOEXEC ఫ్లాగ్తో తెరవబడితే తప్ప, exec సిస్టమ్ కాల్ ఫైల్ హ్యాండిల్లను మూసివేయదు. మా విషయంలో, ఎక్జిక్యూటబుల్ ఫైల్లను ప్రారంభించిన తర్వాత, అన్ని ప్రస్తుత ఫైల్ డిస్క్రిప్టర్లు సేవ్ చేయబడతాయి.
కన్సోల్లో తనిఖీ చేయండి:
[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
మీరు చూడగలిగినట్లుగా, మా పైప్ యొక్క ప్రత్యేక సంఖ్య రెండు ప్రక్రియలలో ఒకే విధంగా ఉంటుంది. కాబట్టి ఒకే పేరెంట్తో రెండు వేర్వేరు ప్రక్రియల మధ్య మనకు కనెక్షన్ ఉంది.
బాష్ ఉపయోగించే సిస్టమ్ కాల్ల గురించి తెలియని వారికి, స్ట్రేస్ ద్వారా ఆదేశాలను అమలు చేయాలని మరియు అంతర్గతంగా ఏమి జరుగుతుందో చూడాలని నేను బాగా సిఫార్సు చేస్తున్నాను, ఉదాహరణకు ఇలా:
strace -s 1024 -f bash -c "ls | grep hello"
తక్కువ డిస్క్ స్థలం మరియు ప్రాసెస్ను పునఃప్రారంభించకుండా డేటాను సేవ్ చేయడానికి ప్రయత్నిస్తున్నప్పుడు మా సమస్యకు తిరిగి వెళ్దాం. డిస్క్కి సెకనుకు దాదాపు 1 మెగాబైట్ని వ్రాసే చిన్న ప్రోగ్రామ్ను వ్రాద్దాం. అంతేకాకుండా, కొన్ని కారణాల వల్ల మేము డిస్క్కి డేటాను వ్రాయలేకపోతే, మేము దీన్ని విస్మరించి, సెకనులో డేటాను మళ్లీ వ్రాయడానికి ప్రయత్నిస్తాము. నేను పైథాన్ని ఉపయోగిస్తున్న ఉదాహరణలో, మీరు ఏదైనా ఇతర ప్రోగ్రామింగ్ భాషని ఉపయోగించవచ్చు.
[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) లేదా అప్లికేషన్లో వివిధ స్థాయిల లాగింగ్ను ఉపయోగిస్తారు. ఇప్పటికే నడుస్తున్న ప్రోగ్రామ్ను వాస్తవానికి వ్రాయడానికి మరియు మార్చగల సామర్థ్యాన్ని Linux అందిస్తుంది, ఉదాహరణకు, వేరియబుల్స్ విలువలను మార్చడం, బ్రేక్పాయింట్ సెట్ చేయడం మొదలైనవి.
ఫైల్ను వ్రాయడానికి తగినంత డిస్క్ స్థలం లేకపోవడం గురించి అసలు ప్రశ్నకు తిరిగి వస్తున్నప్పుడు, సమస్యను అనుకరించడానికి ప్రయత్నిద్దాం.
మన విభజన కోసం ఫైల్ను సృష్టిద్దాం, దానిని మనం ప్రత్యేక డిస్క్గా మౌంట్ చేస్తాము:
[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% ఆక్రమించబడింది.
పని యొక్క పరిస్థితుల ప్రకారం, మేము కోల్పోలేని చాలా ముఖ్యమైన డేటాను రికార్డ్ చేయడానికి ప్రయత్నిస్తున్నామని మేము గుర్తుంచుకోవాలి. మరియు అదే సమయంలో, మేము ప్రక్రియను పునఃప్రారంభించకుండా సేవను పరిష్కరించాలి.
మనకు ఇప్పటికీ డిస్క్ స్థలం ఉందని అనుకుందాం, కానీ వేరే విభజనలో, ఉదాహరణకు /హోమ్లో.
మన కోడ్ను “ఫ్లైలో రీప్రోగ్రామ్” చేయడానికి ప్రయత్నిద్దాం.
డిస్క్ స్థలం మొత్తాన్ని తిన్న మా ప్రక్రియ యొక్క PIDని చూద్దాం:
[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
పైథాన్ ఏ సిస్టమ్ కాల్ చేస్తుందో గుర్తుంచుకోండి (పైన మనం స్ట్రేస్ రన్ చేసి ఓపెన్ కాల్ని ఎక్కడ కనుగొన్నామో చూడండి), ఫైల్ని తెరవడానికి మన కోడ్ని ప్రాసెస్ చేస్తున్నప్పుడు, మన ప్రాసెస్ తరపున మనమే అదే చేస్తాము, అయితే మనకు O_WRONLY|O_CREAT| O_TRUNC బిట్లు సంఖ్యా విలువతో భర్తీ చేయబడతాయి. దీన్ని చేయడానికి, కెర్నల్ మూలాలను తెరవండి, ఉదాహరణకు
#O_WRONLY 00000001ని నిర్వచించండి
#O_CREAT 00000100ని నిర్వచించండి
#O_TRUNC 00001000ని నిర్వచించండి
మేము అన్ని విలువలను ఒకటిగా కలుపుతాము, మనకు 00001101 వస్తుంది
మేము మా కాల్ని gdb నుండి అమలు చేస్తాము
(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
మేము పైపుతో ఉదాహరణను గుర్తుంచుకుంటాము - బాష్ ఫైల్ డిస్క్రిప్టర్లను ఎలా మారుస్తుంది మరియు మేము ఇప్పటికే 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 నుండి నిష్క్రమించండి
(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
ఇప్పుడు పైప్లో ముగిసే మొత్తం డేటా స్వయంచాలకంగా నెట్క్యాట్లోని 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
డేటా సేవ్ చేయబడింది, సమస్య పరిష్కరించబడుతుంది.
డెగిరో నుండి నా సహోద్యోగులకు హలో చెప్పడానికి నేను ఈ అవకాశాన్ని ఉపయోగించుకుంటాను.
రేడియో-టి పాడ్క్యాస్ట్లను వినండి.
అంతా మంచి జరుగుగాక.
హోంవర్క్గా, మీరు ఈ క్రింది ఆదేశాన్ని అమలు చేస్తే, క్యాట్ అండ్ స్లీప్ డిస్క్రిప్టర్స్ ఫైల్లో ఏమి ఉంటుందో ఆలోచించమని నేను మీకు సూచిస్తున్నాను:
[user@localhost ~]$ cat /dev/zero 2>/dev/null| sleep 10000
మూలం: www.habr.com