උදාහරණ සමඟ ලිනක්ස් හි ගොනු විස්තරය

වරක්, සම්මුඛ පරීක්ෂණයකදී, මගෙන් ඇසුවා, තැටියේ ඉඩ මදි බව නිසා සේවාවක් ක්‍රියා නොකරනු ඇත්නම් ඔබ කුමක් කරන්නේද?

ඇත්ත වශයෙන්ම, මම පිළිතුරු දුන්නේ මෙම ස්ථානය අල්ලාගෙන ඇත්තේ කුමක්දැයි මම බලා සිටින බවත්, හැකි නම්, මම එම ස්ථානය පිරිසිදු කරන බවත්ය.
එවිට සම්මුඛ පරීක්ෂකවරයා ඇසුවේ, කොටසේ නිදහස් ඉඩක් නොමැති නම්, නමුත් ඔබට සියලු ඉඩ ලබා ගන්නා ගොනු කිසිවක් නොපෙනේ නම් කුමක් කළ යුතුද?

මෙයට මම පැවසුවේ ඔබට සැමවිටම විවෘත ගොනු විස්තර කිරීම් දෙස බැලිය හැකි බවයි, උදාහරණයක් ලෙස lsof විධානය සමඟ, සහ පවතින සියලුම ඉඩ ලබාගෙන ඇත්තේ කුමන යෙදුමද යන්න තේරුම් ගත හැකි අතර, දත්ත අවශ්‍යද යන්න මත පදනම්ව ඔබට තත්වයන් අනුව ක්‍රියා කළ හැකි බව. .

සම්මුඛ පරීක්ෂකවරයා අවසාන වචනයෙන් මට බාධා කළේය, ඔහුගේ ප්‍රශ්නයට එක් කරමින්: "අපිට දත්ත අවශ්‍ය නැතැයි සිතන්න, එය නිදොස් කිරීමේ ලොගයක් පමණි, නමුත් යෙදුම නිදොස් කිරීමක් ලිවීමට නොහැකි නිසා ක්‍රියා නොකරයි"?

“හරි,” මම පිළිතුරු දුන්නා, “අපිට යෙදුම් වින්‍යාසය තුළ නිදොස්කරණය අක්‍රිය කර එය නැවත ආරම්භ කළ හැකිය.”
සම්මුඛ පරීක්ෂකවරයා විරුද්ධ විය: “නැහැ, අපට යෙදුම නැවත ආරම්භ කළ නොහැක, අපට තවමත් වැදගත් දත්ත මතකයේ ගබඩා කර ඇත, සහ වැදගත් සේවාදායකයින් සේවාවටම සම්බන්ධ වී ඇත, අපට නැවත සම්බන්ධ වීමට බල කළ නොහැක.”

“හරි,” මම කිව්වා, “අපට යෙදුම නැවත ආරම්භ කළ නොහැකි නම් සහ දත්ත අපට වැදගත් නොවේ නම්, අපට මෙම විවෘත ගොනුව ls විධානයේ නොපෙනුනත්, ගොනු විස්තරය හරහා සරලව ඉවත් කළ හැකිය. ගොනු පද්ධතිය මත."

සම්මුඛ පරීක්ෂකවරයා සතුටු වූ නමුත් මම එසේ නොකළෙමි.

එවිට මම සිතුවෙමි, මගේ දැනුම පරීක්ෂා කරන පුද්ගලයා ගැඹුරට නොයන්නේ ඇයි? නමුත් දත්ත සියල්ලටම වඩා වැදගත් නම් කුමක් කළ යුතුද? අපට ක්‍රියාවලියක් නැවත ආරම්භ කළ නොහැකි නම්, සහ ක්‍රියාවලිය නිදහස් ඉඩක් නොමැති කොටසක ගොනු පද්ධතියට ලියයි නම් කුමක් කළ යුතුද? දැනටමත් ලියා ඇති දත්ත පමණක් නොව, මෙම ක්‍රියාවලිය ලියන හෝ ලිවීමට උත්සාහ කරන දත්තද අපට නැති කර ගත නොහැකි නම් කුමක් කළ යුතුද?

ටුසික්

මගේ වෘත්තීය ජීවිතය ආරම්භයේදී, පරිශීලක තොරතුරු ගබඩා කිරීමට අවශ්‍ය කුඩා යෙදුමක් නිර්මාණය කිරීමට මම උත්සාහ කළෙමි. ඊට පස්සේ මම හිතුවා, මම කොහොමද පරිශීලකයාගේ දත්තවලට ගැලපෙන්නේ කියලා. නිදසුනක් වශයෙන්, මට Ivanov Ivan Ivanovich ඇත, ඔහුට යම් තොරතුරු තිබේ, නමුත් මම ඔවුන් සමඟ මිතුරු වන්නේ කෙසේද? "ටුසික්" නම් බල්ලා අයිති මේ අයිවන්ටම බව මට කෙලින්ම පෙන්වා දිය හැකිය. නමුත් ඔහු තම නම වෙනස් කර අයිවන් වෙනුවට ඔලියා බවට පත් වුවහොත් කුමක් කළ යුතුද? එවිට අපගේ ඔලියා ඉවානොව්නා ඉවානෝවාට තවදුරටත් බල්ලෙකු නොසිටින අතර අපගේ ටුසික් තවමත් නොපවතින අයිවන්ට අයත් වනු ඇත. සෑම පරිශීලකයෙකුටම අනන්‍ය හඳුනාගැනීමක් (ID) ලබා දුන් දත්ත සමුදායක් මෙම ගැටළුව විසඳීමට උපකාරී වූ අතර මගේ Tuzik මෙම හැඳුනුම්පතට සම්බන්ධ කර ඇත, එය සැබවින්ම අනුක්‍රමික අංකයක් විය. මේ අනුව, ටුසික්ගේ හිමිකරුට හැඳුනුම්පත් අංක 2 තිබූ අතර, යම් අවස්ථාවක දී අයිවන් මෙම හැඳුනුම්පත යටතේ සිටි අතර, පසුව ඔලියා මෙම හැඳුනුම්පත යටතේම විය. මනුෂ්‍යත්වය සහ සත්ව පාලනය පිළිබඳ ගැටලුව ප්‍රායෝගිකව විසඳා ඇත.

ගොනු විස්තරකය

මෙම ගොනුව සමඟ ක්‍රියා කරන ගොනුවේ සහ වැඩසටහනේ ගැටලුව අපේ බල්ලාගේ සහ මිනිසාගේ ප්‍රශ්නයට ආසන්න වශයෙන් සමාන වේ. මම ivan.txt නම් ගොනුවක් විවෘත කර එහි ටුසික් යන වචනය ලිවීමට පටන් ගත් නමුත් ගොනුවේ පළමු අකුර “t” ලිවීමට පමණක් සමත් වූ අතර, මෙම ගොනුව යමෙකු විසින් olya.txt ලෙස නම් කරන ලදී. නමුත් ගොනුව එලෙසම පවතින අතර, මට තවමත් මගේ ace එක එහි සටහන් කිරීමට අවශ්‍යයි. පද්ධති ඇමතුමකින් ගොනුවක් විවෘත කරන සෑම අවස්ථාවකම විවෘත ඕනෑම ක්‍රමලේඛන භාෂාවකින් මට ගොනුවකට යොමු කරන අද්විතීය හැඳුනුම්පතක් ලැබේ, මෙම හැඳුනුම්පත ගොනු විස්තරය වේ. ඊළඟට මෙම ගොනුව සමඟ කුමක් කරන්නේද සහ කවුරුන් කරන්නේද යන්න කිසිසේත්ම වැදගත් නොවේ, එය මකා දැමිය හැකිය, එය නැවත නම් කළ හැකිය, හිමිකරු වෙනස් කළ හැකිය, නැතහොත් කියවීමේ සහ ලිවීමේ අයිතිය ඉවත් කළ හැකිය, මට තවමත් ප්‍රවේශය ඇත එයට, ගොනුව විවෘත කරන අවස්ථාවේදී, එය කියවීමට සහ/හෝ ලිවීමට මට අයිතියක් තිබූ අතර මම එය සමඟ වැඩ කිරීම ආරම්භ කළෙමි, එයින් අදහස් කරන්නේ මම එය දිගටම කළ යුතු බවයි.

Linux හි, libc පුස්තකාලය එක් එක් ධාවනය වන යෙදුම් (ක්‍රියාවලිය) සඳහා 3 අංක සහිත විස්තර ගොනු 0,1,2ක් විවෘත කරයි. වැඩි විස්තර සබැඳි වලින් සොයාගත හැකිය මිනිසා stdio и මිනිසා stdout

  • ගොනු විස්තරය 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 ආරක්ෂිතව නොසලකා හැරිය හැක; එය එහි අවශ්‍යතා සඳහා විවෘත කරන ලද්දේ බැෂ් විසින්ම මිස සම්බන්ධිත පුස්තකාලය මගින් නොවේ.

දැන් සියලුම විස්තර ගොනු 3 ව්‍යාජ පර්යන්ත උපාංගය සමඟ සම්බන්ධ වේ /dev/pts, නමුත් අපට තවමත් ඒවා හැසිරවිය හැකිය, උදාහරණයක් ලෙස, ඒවා දෙවන කොන්සෝලය තුළ ධාවනය කරන්න

[user@localhost ]$ echo "hello world" > /proc/15771/fd/0

සහ පළමු කොන්සෝලය තුළ අපි දකිනු ඇත

[user@localhost ]$ hello world

යළි-යොමුවීම් සහ පයිප්ප

bash ඇතුළුව ඕනෑම ක්‍රියාවලියකදී ඔබට මෙම විස්තර ගොනු 3 පහසුවෙන් අභිබවා යා හැක, උදාහරණයක් ලෙස ක්‍රියාවලි දෙකක් සම්බන්ධ කරන පයිප්පයක් හරහා, බලන්න

[user@localhost ]$ cat /dev/zero | sleep 10000

ඔබට මෙම විධානය ඔබම ක්‍රියාත්මක කළ හැකිය strace -f සහ ඇතුළත සිදුවන්නේ කුමක්දැයි බලන්න, නමුත් මම ඔබට කෙටියෙන් කියන්නම්.

PID 15771 සමඟින් අපගේ parent bash ක්‍රියාවලිය අපගේ විධානය විග්‍රහ කර අපට ක්‍රියාත්මක කිරීමට අවශ්‍ය විධාන ගණන හරියටම තේරුම් ගනී, අපගේ නඩුවේදී ඒවායින් දෙකක් තිබේ: cat සහ sleep. 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

ඉන්පසු පද්ධති ඇමතුම භාවිතා කරන්න ක්ලෝන 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
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 සමඟ පළමු ළමා බෂ් ක්‍රියාවලියේදී, පද්ධතිය ඇමතුම dup2, අපගේ STDOUT ගොනු විස්තරය අංක 1 පයිප්පයට යොමු කරන ගොනු විස්තරයකට වෙනස් කරයි, අපගේ නඩුවේදී එය අංක 3 වේ. මේ අනුව, PID 9004 සමඟ පළමු ළමා ක්‍රියාවලිය STDOUT වෙත ලියන සෑම දෙයක්ම ස්වයංක්‍රීයව පයිප්ප බෆරය තුළ අවසන් වේ.

PID 9005 සමඟ දෙවන ළමා ක්‍රියාවලියේදී, bash විසින් STDIN අංකය 2 යන ගොනු විස්තරය වෙනස් කිරීමට dup0 භාවිතා කරයි. දැන් PID 9005 සමඟ අපගේ දෙවන bash කියවන සියල්ල පයිප්පයෙන් කියවනු ඇත.

මෙයින් පසු, අංක 3 සහ 4 ගොනු විස්තර කිරීම් තවදුරටත් භාවිතා නොකරන බැවින් ළමා ක්‍රියාවලීන්හි වසා ඇත.

මම හිතාමතාම ගොනු විස්තරය 255 නොසලකා හරිමි; එය බාෂ් විසින්ම අභ්‍යන්තර අරමුණු සඳහා භාවිතා කරන අතර ළමා ක්‍රියාවලීන් තුළද වසා දමනු ඇත.

ඊළඟට, PID 9004 සමඟ පළමු ළමා ක්‍රියාවලියේදී, bash පද්ධති ඇමතුමක් භාවිතා කිරීමට පටන් ගනී එච් අපි විධාන රේඛාවේ සඳහන් කළ ක්‍රියාත්මක කළ හැකි ගොනුව, අපගේ නඩුවේදී එය /usr/bin/cat වේ.

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

ඔබට පෙනෙන පරිදි, අපගේ පයිප්පයේ අද්විතීය අංකය ක්රියාවලීන් දෙකෙහිම සමාන වේ. මේ අනුව අපට එකම මාපියෙකු සමඟ විවිධ ක්‍රියාවලි දෙකක් අතර සම්බන්ධයක් ඇත.

bash භාවිතා කරන පද්ධති ඇමතුම් ගැන නොදන්නා අය සඳහා, විධාන strace හරහා ක්‍රියාත්මක කිරීම සහ අභ්‍යන්තරව සිදුවන දේ බැලීම මම තරයේ නිර්දේශ කරමි, උදාහරණයක් ලෙස මේ වගේ:

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

ඔබට පෙනෙන පරිදි, ගොනු ප්රමාණය වැඩි වන අතර අපගේ කඳට වැඩ නොකළේය. පද්ධති ඇමතුම් ලේඛන දෙස බලමු විවෘත. අපි ගොනුවක් විවෘත කිරීමේදී O_APPEND ධජය භාවිතා කරන්නේ නම්, එක් එක් ලිවීමේදී, මෙහෙයුම් පද්ධතිය ගොනු ප්‍රමාණය පරීක්ෂා කර ගොනුවේ අවසානය දක්වා දත්ත ලියන අතර මෙය පරමාණුකව සිදු කරයි. මෙමගින් නූල් හෝ ක්‍රියාවලි කිහිපයක් එකම ගොනුවකට ලිවීමට ඉඩ සලසයි. නමුත් අපේ කේතයේ අපි මෙම ධජය භාවිතා කරන්නේ නැහැ. අමතර ලිවීම සඳහා අපි ගොනුව විවෘත කළහොත් පමණක් අපට කඳට පසු lsof හි වෙනස් ගොනු ප්‍රමාණයක් දැකිය හැකිය, එනම් ඒ වෙනුවට අපගේ කේතයේ

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 හි.

අපගේ කේතය "පියාසරයේදී නැවත වැඩසටහන්" කිරීමට උත්සාහ කරමු.

අපගේ ක්‍රියාවලියේ 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

Python කුමන පද්ධති ඇමතුමක් ලබා දෙන්නේද යන්න මතක තබා ගනිමින් (ඉහත බලන්න, අපි ස්ට්‍රේස් ධාවනය කර විවෘත ඇමතුම සොයාගත් ස්ථානය බලන්න), ගොනුවක් විවෘත කිරීමට අපගේ කේතය සැකසීමේදී, අපගේ ක්‍රියාවලිය වෙනුවෙන් අපි එයම කරමු, නමුත් අපට 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

පයිප්ප සමඟ උදාහරණය අපට මතකයි - 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 පිටවන්න

(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

දත්ත නැති වී නැත, යෙදුම ක්‍රියා කරයි, ලොග් නව ස්ථානයකට ලියා ඇත.

අපි කාර්යය ටිකක් සංකීර්ණ කරමු

දත්ත අපට වැදගත් යැයි සිතමු, නමුත් අපට කිසිදු කොටසක තැටි ඉඩක් නොමැති අතර අපට තැටිය සම්බන්ධ කළ නොහැක.

අපට කළ හැක්කේ අපගේ දත්ත කොතැනකට හෝ හරවා යැවීමයි, උදාහරණයක් ලෙස පයිප්පයට, සහ අනෙක් අතට, පයිප්පයේ සිට ජාලයට දත්ත යම් වැඩසටහනක් හරහා හරවා යැවීමයි, උදාහරණයක් ලෙස netcat.
අපට 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

දැන් අපි කෙසේ හෝ මෙම පයිප්පයට ඇතුළු වන සියලුම දත්ත ජාලය හරහා වෙනත් සේවාදායකයකට ඔතා ගත යුතුය; මේ සඳහා එකම netcat සුදුසු වේ.

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

දත්ත සුරකිනු ඇත, ගැටළුව විසඳනු ලැබේ.

මම Degiro සිට මගේ සගයන්ට ආයුබෝවන් කියන්න මෙය අවස්ථාවක් කර ගනිමි.
රේඩියෝ-ටී පොඩ්කාස්ට් වලට සවන් දෙන්න.

සියල්ලම සාර්ථක වෙන්න කියා ප්රාර්ථනා කරනවා.

ගෙදර වැඩ ලෙස, ඔබ පහත විධානය ක්‍රියාත්මක කරන්නේ නම්, cat and sleep විස්තර කරන ක්‍රියාවලි ගොනුවේ ඇති දේ ගැන සිතා බැලීමට මම ඔබට යෝජනා කරමි:

[user@localhost ~]$ cat /dev/zero 2>/dev/null| sleep 10000

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න