এই স্ক্রিপ্টটি কীভাবে নিশ্চিত করে যে কেবল নিজের একটি দৃষ্টান্ত চলছে?


22

১৯ আগস্ট ২০১৩-এ, র্যান্ডাল এল শোয়ার্জ এই শেল স্ক্রিপ্টটি পোস্ট করেছেন , এটি লিনাক্স-এ নিশ্চিত করার উদ্দেশ্যে করা হয়েছিল, "বর্ণের শর্ত ছাড়াই বা লক ফাইলগুলি পরিষ্কার না করে [স্ক্রিপ্টের কেবলমাত্র একটি উদাহরণ চলছে" ":

#!/bin/sh
# randal_l_schwartz_001.sh
(
    if ! flock -n -x 0
    then
        echo "$$ cannot get flock"
        exit 0
    fi
    echo "$$ start"
    sleep 10 # for testing.  put the real task here
    echo "$$ end"
) < $0

এটি বিজ্ঞাপন হিসাবে কাজ করছে বলে মনে হচ্ছে:

$ ./randal_l_schwartz_001.sh & ./randal_l_schwartz_001.sh
[1] 11863
11863 start
11864 cannot get flock
$ 11863 end

[1]+  Done                    ./randal_l_schwartz_001.sh
$

আমি যা বুঝতে পারি তা এখানে:

  • স্ক্রিপ্টটি <তার নিজস্ব সামগ্রীর একটি অনুলিপি (যেমন থেকে $0) একটি সাবসেলের এসটিডিআইএন (অর্থাত্ ফাইল বর্ণনাকারী 0) -এ পুনঃনির্দেশ করে ।
  • সাব-শেলের মধ্যে, স্ক্রিপ্টটি flock -n -xফাইল বর্ণনাকারীতে একটি অ-ব্লকিং, এক্সক্লুসিভ লক ( ) পাওয়ার চেষ্টা করে 0
    • যদি সেই প্রচেষ্টা ব্যর্থ হয়, সাবশেলটি প্রস্থান করে (এবং এটির জন্য আর কিছুই নেই বলে মূল স্ক্রিপ্টটি ঘটে)।
    • পরিবর্তে যদি প্রচেষ্টা সফল হয় তবে সাব-শেলগুলি পছন্দসই কাজটি চালায়।

আমার প্রশ্নগুলি এখানে:

  • স্ক্রিপ্টটি কেন অন্য কোনও ফাইলের বিষয়বস্তু বলার পরিবর্তে সাবসেলের দ্বারা উত্তরাধিকার সূত্রে প্রাপ্ত কোনও ফাইল বর্ণনাকারীর কাছে পুনর্নির্দেশ করা দরকার ? (আমি একটি ভিন্ন ফাইল থেকে পুনর্নির্দেশের চেষ্টা করেছি এবং উপরের মতো পুনরায় চলার চেষ্টা করেছি এবং মৃত্যুদণ্ডের আদেশ পরিবর্তন হয়েছে: ব্যাকগ্রাউন্ডহীন টাস্কটি ব্যাকগ্রাউন্ডের আগে লকটি অর্জন করেছে So সুতরাং, সম্ভবত ফাইলটির নিজস্ব বিষয়বস্তু ব্যবহার করা জাতিগত পরিস্থিতি এড়িয়ে চলে; তবে কীভাবে?)
  • স্ক্রিপ্টটি কেন, যে কোনও উপায়ে সাবशेলের উত্তরাধিকার সূত্রে প্রাপ্ত কোনও ফাইল বর্ণনাকারীর কাছে পুনর্নির্দেশ করা দরকার?
  • কেন একটি 0শেলের মধ্যে ফাইল বর্ণনাকারীর উপর একটি এক্সক্লুসিভ লক রাখা একই স্ক্রিপ্টের অনুলিপি, অন্য শেলের মধ্যে চলমান, ফাইল বিবরণীতে একচেটিয়া লক পাওয়া থেকে বাধা দেয় 0? শাঁস মান ফাইল বর্ণনাকারী (তাদের নিজস্ব আলাদা কাদি না 0, 1এবং 2, অর্থাত্ stdin, stdout- এ, এবং stderr)?

আপনি যখন পরীক্ষা থেকে আলাদা ফাইল থেকে পুনর্নির্দেশের চেষ্টা করেছিলেন তখন আপনার সঠিক পরীক্ষা প্রক্রিয়াটি কী ছিল?
ফ্রেইহাইট

1
আমি মনে করি আপনি এই লিঙ্কটি উল্লেখ করতে পারেন। stackoverflow.com/questions/185451/…
দেব পাইকার

উত্তর:


22

স্ক্রিপ্টটি কেন অন্য কোনও ফাইলের বিষয়বস্তু বলার পরিবর্তে সাবসেলের দ্বারা উত্তরাধিকার সূত্রে প্রাপ্ত কোনও ফাইল বর্ণনাকারীর কাছে পুনর্নির্দেশ করা দরকার?

আপনি যে কোনও ফাইল ব্যবহার করতে পারবেন, যতক্ষণ না স্ক্রিপ্টের সমস্ত অনুলিপি একই ব্যবহার করে। ব্যবহার $0শুধু স্ক্রিপ্ট নিজেই লক বেঁধে: আপনি স্ক্রিপ্ট কপি এবং কিছু অন্যান্য ব্যবহারের জন্য এটি পরিবর্তন করেন, তাহলে আপনি লক ফাইলের জন্য একটি নতুন নাম নিয়ে আসা প্রয়োজন হবে না। এটি সুবিধাজনক।

যদি স্ক্রিপ্টটি কোনও সিমলিংকের মাধ্যমে কল করা হয় তবে লকটি আসল ফাইলে রয়েছে, লিঙ্কটি নয়।

(অবশ্যই, যদি কোনও প্রক্রিয়া স্ক্রিপ্টটি চালায় এবং এটিকে আসল পথের পরিবর্তে জিরোথ আর্গুমেন্ট হিসাবে একটি মেক আপ মান দেয়, তবে এটি বিরতি দেয় But তবে এটি খুব কমই সম্পন্ন হয়েছে))

(আমি একটি পৃথক ফাইল ব্যবহার করার চেষ্টা করেছি এবং উপরের মতো পুনরায় চলার চেষ্টা করেছি এবং কার্যকর করার আদেশটি পরিবর্তন হয়েছে)

আপনি কি নিশ্চিত যে ফাইলটি ব্যবহৃত হয়েছিল, এবং কেবল এলোমেলো পরিবর্তনের কারণে নয়? পাইপলাইনের মতো, কমান্ডগুলি কীভাবে চালিত হবে তা নিশ্চিত হওয়ার কোনও উপায় নেই cmd1 & cmd। এটি বেশিরভাগই ওএসের শিডিয়ুলার অবধি। আমি আমার সিস্টেমে এলোমেলো পরিবর্তন পাই।

স্ক্রিপ্টটি কেন, যে কোনও উপায়ে সাবशेলের উত্তরাধিকার সূত্রে প্রাপ্ত কোনও ফাইল বর্ণনাকারীর কাছে পুনর্নির্দেশ করা দরকার?

দেখে মনে হচ্ছে এটি শেল নিজেই কেবলমাত্র flockইউটিলিটিটি ধরে রাখার পরিবর্তে লকটি ধারণ করে ফাইল বিবরণির একটি অনুলিপি ধারণ করে। এর সাথে তৈরি একটি লক flock(2)প্রকাশিত হয় যখন এতে থাকা ফাইল বর্ণনাকারী এটি বন্ধ থাকে।

flockফাইলের নামের উপর ভিত্তি করে লক নেওয়া, এবং একটি বাহ্যিক কমান্ড চালানো (যার ক্ষেত্রে flockপ্রয়োজনীয় ওপেন ফাইল বর্ণনাকারী ধারণ করে), বা বাইরে থেকে কোনও ফাইল বিবরণী গ্রহণের জন্য দুটি পদ্ধতি রয়েছে, সুতরাং বাইরের প্রক্রিয়াটি ধরে রাখার জন্য দায়বদ্ধ এটা।

নোট করুন যে ফাইলের বিষয়বস্তু এখানে প্রাসঙ্গিক নয়, এবং কোনও অনুলিপি তৈরি করা হয়নি। সাবশেলের পুনঃনির্দেশটি কোনও তথ্যই নিজের চারপাশে অনুলিপি করে না, এটি কেবল ফাইলটিতে একটি হ্যান্ডেল খোলে।

কেন একটি শেলের মধ্যে ফাইল বর্ণনাকারী 0 এ একচেটিয়া লক ধরে রাখা একই স্ক্রিপ্টের অনুলিপি, অন্য শেলের মধ্যে চলমান, ফাইল বর্ণনাকারী 0 তে একচেটিয়া লক পাওয়া থেকে বাধা দেয়? শেলগুলির নিজস্ব স্ট্যান্ডার্ড ফাইল বর্ণনাকারীর পৃথক অনুলিপিগুলি (0, 1, এবং 2, যেমন এসটিডিএন, এসটিডিআউট এবং এসটিডিআরআর) নেই?

হ্যাঁ, তবে লকটি ফাইলটিতে রয়েছে , ফাইল বিবরণকারী নয়। ফাইলটির কেবল একটি খোলার উদাহরণটি একবারে লকটি ধরে রাখতে পারে।


আমি মনে করি execলক ফাইলটিতে একটি হ্যান্ডেল খোলার মাধ্যমে সাবসেল ছাড়াই আপনার এটি করা উচিত :

$ cat lock.sh
#!/bin/sh

exec 9< "$0"

if ! flock -n -x 9; then
    echo "$$/$1 cannot get flock" 
    exit 0
fi

echo "$$/$1 got the lock"
sleep 2
echo "$$/$1 exit"

$ ./lock.sh bg & ./lock.sh fg ; wait; echo
[1] 11362
11363/fg got the lock
11362/bg cannot get flock
11363/fg exit
[1]+  Done                    ./lock.sh bg

1
{ }পরিবর্তে ব্যবহার ( )করাও কাজ করবে এবং সাব-শেল এড়িয়ে যাবে।
আর ..

G + পোস্টে দেওয়া মন্তব্যে আরও নীচে, সেখানে কেউ কেউ একই পদ্ধতি ব্যবহার করার পরামর্শ দিয়েছিল exec
ডেভিড জেড

@ আর .., ওহ, নিশ্চিত তবে এটি এখনও প্রকৃত স্ক্রিপ্টের চারপাশে অতিরিক্ত ধনুর্বন্ধনী সহ কুশ্রী।
ইল্কচাচু

9

একটি ফাইল লক একটি ফাইলের সাথে একটি ফাইলের বর্ণনার মাধ্যমে সংযুক্ত থাকে । উচ্চ স্তরে, স্ক্রিপ্টের একটি উদাহরণে ক্রিয়াকলাপগুলির ক্রমটি হ'ল:

  1. লকটি সংযুক্ত করা আছে এমন ফাইলটি খুলুন ("লক ফাইল")।
  2. লক ফাইলটিতে একটি লক নিন।
  3. স্টাফ কর
  4. লক ফাইলটি বন্ধ করুন। এটি ফাইলটি খোলার মাধ্যমে তৈরি করা ফাইলের বর্ণনার সাথে সংযুক্ত লকটি প্রকাশ করে।

লকটি ধরে রাখা চলমান একই স্ক্রিপ্টের অন্য অনুলিপি প্রতিরোধ করে কারণ লকগুলি সেটাই করে। যতক্ষণ না কোনও ফাইলের একচেটিয়া লকটি সিস্টেমে কোথাও উপস্থিত থাকে, ততক্ষণ আলাদা ফাইলের বর্ণনার মধ্য দিয়ে এমনকি একই লকের দ্বিতীয় উদাহরণ তৈরি করা অসম্ভব।

একটি ফাইল খোলার ফলে একটি ফাইলের বিবরণ তৈরি হয় । এটি একটি কার্নেল অবজেক্ট যার প্রোগ্রামিং ইন্টারফেসগুলিতে খুব বেশি সরাসরি দৃশ্যমানতা নেই। আপনি ফাইল বর্ণনাকারীর মাধ্যমে অপ্রত্যক্ষভাবে ফাইলের বিবরণ অ্যাক্সেস করেন তবে সাধারণত আপনি এটিকে ফাইল অ্যাক্সেস হিসাবে মনে করেন (এর সামগ্রী বা মেটাডেটা পড়া বা লেখা)। লক হল এমন একটি বৈশিষ্ট্য যা ফাইল বা বর্ণনাকারীর পরিবর্তে ফাইল বর্ণনার সম্পত্তি।

শুরুতে, যখন কোনও ফাইল খোলা হয়, ফাইল বর্ণনায় একটি একক ফাইল বর্ণনাকারী থাকে, তবে আরও বর্ণনাকারী তৈরি করা যেতে পারে হয় অন্য বর্ণনাকারী ( dupসিস্টেম কলের পরিবার) তৈরি করে বা উপ-প্রসেসটি কাঁটাচামচ করে (যার পরে পিতা বা মাতা এবং সন্তানের একই ফাইলের বর্ণনায় অ্যাক্সেস রয়েছে)। একটি ফাইল বর্ণনাকারী স্পষ্টভাবে বা যখন প্রক্রিয়াটি মারা যায় তখন বন্ধ হয়ে যেতে পারে। কোনও ফাইলের সাথে সংযুক্ত সর্বশেষ ফাইল বর্ণনাকারী বন্ধ হয়ে গেলে ফাইলের বিবরণ বন্ধ হয়ে যায়।

উপরে বর্ণিত ক্রিয়াকলাপগুলি ফাইলের বিবরণকে কীভাবে প্রভাবিত করে তা এখানে।

  1. পুনঃনির্দেশটি <$0ফাইলের বিবরণ তৈরি করে সাবশেলে স্ক্রিপ্ট ফাইলটি খুলবে। এই মুহুর্তে বর্ণনার সাথে সংযুক্ত একটি একক ফাইল বর্ণনাকারী রয়েছে: সাবসেলের মধ্যে বর্ণনাকারী সংখ্যা 0।
  2. সাবশেল অনুরোধ করে flockএবং এটি থেকে বেরিয়ে আসার জন্য অপেক্ষা করে। ঝাঁক চলমান অবস্থায়, বর্ণনার সাথে সংযুক্ত দুটি বর্ণনাকারী রয়েছে: সাবশেলে 0 নম্বর এবং ঝাঁক প্রক্রিয়াতে 0 নম্বর। ঝাঁক যখন লকটি নেয় তখন ফাইলের বিবরণের একটি সম্পত্তি সেট করে। যদি অন্য কোনও ফাইলের বর্ণনায় ফাইলে ইতিমধ্যে একটি লক থাকে তবে পশুপথগুলি লকটি নিতে পারে না, কারণ এটি একচেটিয়া লক।
  3. সাবশেল স্টাফ করে। যেহেতু এটিতে এখনও লক সহ বর্ণনায় একটি উন্মুক্ত ফাইল বর্ণনাকারী রয়েছে, সেই বিবরণটি বিদ্যমান রাখে এবং যেহেতু কেউ কখনও লকটি সরায় না তাই এটি তার লকটি রাখে।
  4. সাবশেলটি বন্ধ হয়ে যাওয়া বন্ধনে মারা যায়। এটি লকযুক্ত ফাইলের বর্ণনায় শেষ ফাইল বর্ণনাকারীকে বন্ধ করে দেয় তাই লকটি এই মুহুর্তে অদৃশ্য হয়ে যায়।

স্ক্রিপ্টটি $0যেহেতু পুনর্নির্দেশটি ব্যবহার করে তা হ'ল পুনর্নির্দেশটি শেলটিতে একটি ফাইল খোলার একমাত্র উপায় এবং পুনর্নির্দেশটিকে সক্রিয় রাখা কেবলমাত্র ফাইলের বিবরণকারীকে খোলা রাখার একমাত্র উপায়। সাবশেলটি কখনও কখনও তার স্ট্যান্ডার্ড ইনপুট থেকে পড়ে না, এটি কেবল এটি খোলার প্রয়োজন। এমন ভাষায় যা খোলা এবং বন্ধ কলটিতে সরাসরি অ্যাক্সেস দেয়, আপনি ব্যবহার করতে পারেন

fd = open($0)
flock(fd, LOCK_EX)
do stuff
close(fd)

আপনি যদি execবিল্টিনের সাথে পুনঃনির্দেশটি করেন তবে আপনি শেলের মধ্যে ক্রিয়াকলাপগুলির একই ক্রমটি পেতে পারেন ।

exec <$0
flock -n -x 0
# do stuff
exec <&-

মূল স্ট্যান্ডার্ড ইনপুটটিতে অ্যাক্সেস রাখতে চাইলে স্ক্রিপ্টটি অন্য কোনও ফাইল বর্ণনাকারী ব্যবহার করতে পারে।

exec 3<$0
flock -n -x 0
# do stuff
exec 3<&-

বা একটি সাব-শেল সহ:

(
  flock -n -x 3
  # do stuff
) 3<$0

লকটি স্ক্রিপ্ট ফাইলে থাকতে হবে না। এটি যে কোনও ফাইলে থাকতে পারে যা পড়ার জন্য খোলা যেতে পারে (সুতরাং এটি বিদ্যমান থাকতে হবে, এটি এমন একটি ফাইল টাইপ হতে হবে যা নিয়মিত ফাইল বা নামযুক্ত পাইপের মতো পড়তে পারে তবে ডিরেক্টরি নয়, এবং স্ক্রিপ্ট প্রক্রিয়াটি অবশ্যই থাকতে হবে এটি পড়ার অনুমতি)। স্ক্রিপ্ট ফাইলটির সুবিধা রয়েছে যে এটি উপস্থিত এবং পঠনযোগ্য হওয়ার গ্যারান্টিযুক্ত (প্রান্তের ক্ষেত্রে ব্যতীত যেখানে এটি স্ক্রিপ্টটি চালু হওয়ার সময় এবং স্ক্রিপ্টটি <$0পুনঃনির্দেশে যাওয়ার সময়কালের মধ্যে বাহ্যিকভাবে মুছে ফেলা হয়েছিল )।

যতক্ষণ flockসাফল্য পাওয়া যায়, এবং স্ক্রিপ্টটি এমন একটি ফাইল সিস্টেমে থাকে যেখানে লকগুলি বগি হয় না (কিছু নেটওয়ার্ক ফাইল সিস্টেম যেমন এনএফএস বগি হতে পারে), আমি দেখতে পাচ্ছি না যে কোনও আলাদা লক ফাইল ব্যবহার করে কীভাবে রেসের শর্তটি মঞ্জুর করতে পারে। আমি আপনার পক্ষ থেকে একটি ম্যানিপুলেশন ত্রুটি সন্দেহ।


একটি রেসের শর্ত রয়েছে: স্ক্রিপ্টের কোন উদাহরণটি লক পায় তা আপনি নিয়ন্ত্রণ করতে পারবেন না । ভাগ্যক্রমে, প্রায় সকল উদ্দেশ্যে, এটি কোনও বিষয় নয়।
চিহ্নিত করুন

4
@ মার্ক লক করার জন্য একটি প্রতিযোগিতা রয়েছে, তবে এটি কোনও রেসের শর্ত নয়। একটি দৌড় শর্ত যখন সময় সময় কিছু খারাপ হতে দেয়, যেমন দুটি প্রক্রিয়া একই সময়ে একই সমালোচনামূলক বিভাগে থাকে। কোন প্রক্রিয়াটি সমালোচনামূলক বিভাগে প্রবেশ করবে তা না জেনে প্রত্যাশা করা, এটি কোনও রেসের শর্ত নয়।
গিলস

1
শুধু এফওয়াইআই, "ফাইলের বিবরণ" এর লিঙ্কটি ধারণার নির্দিষ্ট বর্ণনার পরিবর্তে ওপেন গ্রুপ স্পেস সূচী পৃষ্ঠার দিকে ইঙ্গিত করে, যা আমি মনে করি আপনি যা করতে চেয়েছিলেন। অথবা আপনি আপনার পুরোনো উত্তর এখানে পাশাপাশি প্রতি সংযোগ আছে পারে unix.stackexchange.com/a/195164/85039
Sergiy Kolodyazhnyy

5

লক করার জন্য ব্যবহৃত ফাইলটি গুরুত্বহীন, স্ক্রিপ্টটি ব্যবহার করে $0 কারণ এটি এমন একটি ফাইল যা বিদ্যমান বলেই পরিচিত।

আপনার মেশিনটি দুটি কার্য শুরু করতে কতটা দ্রুত সক্ষম তার উপর নির্ভর করে লকগুলি যে অর্ডারে নেওয়া হবে তা কমবেশি এলোমেলো হবে।

আপনি যে কোনো ফাইল বর্ণনাকারী ব্যবহার করতে পারি অগত্যা 0. Lock চালু অনুষ্ঠিত হয় ফাইল ফাইল বর্ণনাকারী বর্ণনাকারী নিজেই না খোলা।

( flock -x 9 || exit 1
  echo 'Locking for 5 secs'; sleep 5; echo 'Done' ) 9>/tmp/lock &
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.