আমি কীভাবে কোনও প্রক্রিয়াটিকে মেরে ফেলতে পারি এবং নিশ্চিত হয়ে উঠতে হবে যে পিআইডি পুনরায় ব্যবহৃত হয়নি


40

ধরুন, উদাহরণস্বরূপ, আপনার কাছে শেল স্ক্রিপ্টের অনুরূপ রয়েছে:

longrunningthing &
p=$!
echo Killing longrunningthing on PID $p in 24 hours
sleep 86400
echo Time up!
kill $p

কৌশলটি করা উচিত, তাই না? প্রক্রিয়াটি প্রারম্ভিকভাবে শেষ হয়ে থাকতে পারে এবং এর পিআইডি পুনর্ব্যবহার করা হতে পারে, যার অর্থ কিছু নিষ্পাপ চাকরির পরিবর্তে এর সিগন্যাল কাতারে বোমা পেতে পারে। অনুশীলনে সম্ভবত এটি গুরুত্বপূর্ণ, তবে তা তবে তা আমাকে উদ্বেগজনক করে তোলে। দীর্ঘমেয়াদী হ্যাকিং নিজে থেকে মরে যাওয়ার জন্য, বা এর পিআইডি এফএস-এ রাখা / সরিয়ে ফেলতে পারে তবে আমি এখানে জেনেরিক পরিস্থিতি নিয়ে ভাবছি।


3
আপনি নিশ্চিত হন যে আপনার লক্ষ্যযুক্ত প্রক্রিয়াটি যদি মারা যায় তবে এটি প্রক্রিয়াতে তার হত্যাকারীকে হত্যা করে।
মাইক্রজারভ

2
killallনামের সাথে কোনটি মিলে যায় তা ব্যবহার করুন , সুতরাং কমপক্ষে আপনি কেবল একই নামের মতো একটি প্রক্রিয়াটি হত্যা করছেন longrunningthing। ধরে নিই আপনার কাছে কেবল একবারে এই চলমান থাকবে।
লরেন্স

8
আপনি মূল প্রক্রিয়াটির প্রারম্ভিক সময় এবং হত্যার আগে, পরীক্ষা করতে পারেন যে পিডের সাথে প্রক্রিয়া শুরু করার সময়টি আপনি যা সংরক্ষণ করেছেন তার সাথে মেলে। যুগল PID, স্টার্ট সময় হয় লিনাক্স প্রক্রিয়া জন্য একটি অনন্য শনাক্তকারী।
বাকুরিউ

1
আমি জিজ্ঞাসা করতে পারি যে আপনার এটি কেন প্রয়োজন? আপনি যে মৌলিক জিনিসটি অর্জন করার চেষ্টা করছেন তা কী? (এমন কিছু যা ধারাবাহিকভাবে চলতে থাকে তবে প্রতি 24 ঘন্টার মধ্যে পুনরায় তৈরি করা হয়?)
অলিভিয়ার ডুলাক

2
@ মাইকজারভ একটি প্রক্রিয়া গ্যারান্টি দিতে পারে না যে তার নিজের মৃত্যুর ঘটনা ঘটলে কিছু ঘটবে।
ক্যাস্পারড

উত্তর:


29

timeoutকমান্ডটি ব্যবহার করা সবচেয়ে ভাল হবে যদি আপনার কাছে এটির অর্থ বোঝানো থাকে:

timeout 86400 cmd

বর্তমান (8.23) জিএনইউ বাস্তবায়ন কমপক্ষে alarm()শিশু প্রক্রিয়াটির জন্য অপেক্ষা করার সময় ব্যবহার করে বা সমতুল্য হয়ে কাজ করে । এটি প্রত্যাবর্তন এবং প্রস্থান করার SIGALRMমধ্যে সরবরাহ করা থেকে রক্ষা করছে বলে মনে হচ্ছে না (কার্যকরভাবে সেই অ্যালার্মটি বাতিল করা )। এই ছোট উইন্ডো চলাকালীন, এমনকি স্টেডারে বার্তা লিখতে পারে (উদাহরণস্বরূপ, যদি শিশুটি একটি কোর ফেলে দেয়) যা আরও রেস উইন্ডোটি বাড়িয়ে তুলবে (অনির্দিষ্টকালের জন্য যদি স্ট্যাডার একটি সম্পূর্ণ পাইপ হয় তবে)।waitpid()timeouttimeout

আমি ব্যক্তিগতভাবে সেই সীমাবদ্ধতার সাথে বেঁচে থাকতে পারি (যা সম্ভবত ভবিষ্যতের সংস্করণে স্থির করা হবে)। timeoutসঠিক প্রস্থান স্থিতি রিপোর্ট করতে, অন্য কোণার কেসগুলি হ্যান্ডেলগুলি (যেমন সিগালআরএম ব্লকড / স্টার্টআপে উপেক্ষা করা, অন্যান্য সিগন্যালগুলি হ্যান্ডেল করা ...) আপনি সম্ভবত হাতে হাতে পরিচালনা করার চেয়ে আরও ভাল যত্ন নেবেন।

একটি অনুমান হিসাবে, আপনি এটি লিখতে পারে perl:

perl -MPOSIX -e '
  $p = fork();
  die "fork: $!\n" unless defined($p);
  if ($p) {
    $SIG{ALRM} = sub {
      kill "TERM", $p;
      exit 124;
    };
    alarm(86400);
    wait;
    exit (WIFSIGNALED($?) ? WTERMSIG($?)+128 : WEXITSTATUS($?))
  } else {exec @ARGV}' cmd

Http://devel.ringlet.net/sysutils/timelimit/timelimit এ একটি কমান্ড রয়েছে ( কয়েক মাসের মধ্যে জিএনইউর পূর্বাভাস দেয় )।timeout

 timelimit -t 86400 cmd

এটির alarm()মতো-মত প্রক্রিয়া ব্যবহার করে তবে SIGCHLDবাচ্চা মারা যাচ্ছে তা সনাক্ত করতে একটি হ্যান্ডলার ইনস্টল করে (থামানো শিশুদের উপেক্ষা করে)। এটি চলার আগে অ্যালার্মটি বাতিল করে waitpid()( SIGALRMএটি মুলতুবি থাকা অবস্থায় সরবরাহ সরবরাহ বাতিল করে না , তবে এটি যেভাবে লেখা হয়েছে, আমি এটি কোনও সমস্যা হিসাবে দেখতে পাচ্ছি না) এবং কল করার আগে হত্যা করে waitpid()(সুতরাং পুনরায় ব্যবহৃত পিডকে হত্যা করতে পারে না) )।

নেটপাইপের একটি timelimitকমান্ডও রয়েছে। এটি এক দশক ধরে অন্য সমস্তগুলির পূর্বাভাস দেয়, আরও একটি পন্থা গ্রহণ করে তবে থামানো আদেশের জন্য সঠিকভাবে কাজ করে না এবং 1সময়সীমা শেষ হওয়ার পরে একটি প্রস্থান স্থিতি ফিরে আসে ।

আপনার প্রশ্নের আরও সরাসরি উত্তর হিসাবে আপনি এরকম কিছু করতে পারেন:

if [ "$(ps -o ppid= -p "$p")" -eq "$$" ]; then
  kill "$p"
fi

অর্থাৎ, পরীক্ষা করুন যে প্রক্রিয়াটি এখনও আমাদের একটি শিশু। আবার, একটি ছোট রেস উইন্ডো রয়েছে ( psসেই প্রক্রিয়াটির স্থিতি পুনরুদ্ধার এবং killএটি হত্যার মধ্যে) যার সময় প্রক্রিয়াটি মারা যেতে পারে এবং এর পিড অন্য প্রক্রিয়া দ্বারা পুনরায় ব্যবহার করা যেতে পারে।

কিছু শাঁস সঙ্গে ( zsh, bash, mksh), আপনি pids পরিবর্তে কাজ চশমা পাস করতে পারেন।

cmd &
sleep 86400
kill %
wait "$!" # to retrieve the exit status

এটি কেবলমাত্র যদি কেবলমাত্র একটি ব্যাকগ্রাউন্ড জব থাকে (অন্যথায় সঠিক জবস্পেক পাওয়া সর্বদা নির্ভরযোগ্যভাবে সম্ভব হয় না) কাজ করে works

যদি এটি কোনও সমস্যা হয় তবে কেবল একটি নতুন শেল উদাহরণ শুরু করুন:

bash -c '"$@" & sleep 86400; kill %; wait "$!"' sh cmd

এটি কাজ করে কারণ শেলটি শিশু মারা যাওয়ার পরে কাজের টেবিল থেকে কাজটি সরিয়ে দেয়। এখানে, শেল কল হওয়ার পরে কোনও রেস উইন্ডো হওয়া উচিত নয় kill(), হয় সিকচিলডি সিগন্যালটি পরিচালনা করা হয়নি এবং পিডটি পুনরায় ব্যবহার করা যাবে না (যেহেতু এটির জন্য অপেক্ষা করা হয়নি), বা এটি পরিচালনা করা হয়েছে এবং প্রক্রিয়া সারণী থেকে কাজ সরানো হয়েছে (এবং killএকটি ত্রুটির কথা জানাবে)। bash'গুলি killঅন্তত ব্লক SIGCHLD এ আগেই প্রসারিত করতে তার কাজ টেবিল ব্যবহারের %পর এবং এটি লোকটিকে অবরোধমুক্ত kill()

মৃত্যুর sleepপরেও এই প্রক্রিয়াটি প্রায় ঝুলে থাকা এড়াতে আরেকটি বিকল্প হ'ল তার পরিবর্তে একটি পাইপ ব্যবহার করা বা হ'ল :cmdbashksh93read -tsleep

{
  {
    cmd 4>&1 >&3 3>&- &
    printf '%d\n.' "$!"
  } | {
    read p
    read -t 86400 || kill "$p"
  }
} 3>&1

এটির এখনও রেসের শর্ত রয়েছে এবং আপনি কমান্ডের প্রস্থান স্থিতি হারাবেন। এটি cmdধরেও নেয় এটি এর এফডি 4 বন্ধ করে দেয় না।

আপনি এই জাতীয়ভাবে একটি রেস-মুক্ত সমাধান বাস্তবায়নের চেষ্টা করতে perlপারেন:

perl -MPOSIX -e '
   $p = fork();
   die "fork: $!\n" unless defined($p);
   if ($p) {
     $SIG{CHLD} = sub {
       $ss = POSIX::SigSet->new(SIGALRM); $oss = POSIX::SigSet->new;
       sigprocmask(SIG_BLOCK, $ss, $oss);
       waitpid($p,WNOHANG);
       exit (WIFSIGNALED($?) ? WTERMSIG($?)+128 : WEXITSTATUS($?))
           unless $? == -1;
       sigprocmask(SIG_UNBLOCK, $oss);
     };
     $SIG{ALRM} = sub {
       kill "TERM", $p;
       exit 124;
     };
     alarm(86400);
     pause while 1;
   } else {exec @ARGV}' cmd args...

(যদিও এটি অন্য ধরণের কোণার কেসগুলি পরিচালনা করার জন্য উন্নত করা দরকার)।

প্রক্রিয়া গ্রুপগুলি ব্যবহার করে অন্য একটি রেস-মুক্ত পদ্ধতি হতে পারে:

set -m
((sleep 86400; kill 0) & exec cmd)

তবে মনে রাখবেন যে প্রসেস গ্রুপগুলি ব্যবহার করে কোনও টার্মিনাল ডিভাইসে জড়িত I / O থাকলে পার্শ্ব-প্রতিক্রিয়া থাকতে পারে। এটির অতিরিক্ত সুবিধা রয়েছে যদিও এর ফলে তৈরি অন্যান্য সমস্ত অতিরিক্ত প্রক্রিয়াগুলি মেরে ফেলতে পারে cmd


4
কেন প্রথমে সেরা পদ্ধতির উল্লেখ নেই?
দেলতাব

2
@ দালতাব: timeoutবহনযোগ্য নয়, উত্তরে প্রথমে একটি বহনযোগ্য সমাধানের কথা বলা হয়েছে।
cuonglm

1
@ দালতাব: এটি কীভাবে জিনিসগুলি কাজ করে এবং বিশেষত "সাধারণ জ্ঞান" পদ্ধতিটি কীভাবে ব্যর্থ হতে পারে সে সম্পর্কে অন্তর্দৃষ্টি দেয় (স্টিফেন প্রথমে একজনকে মাছ ধরা শেখাতে পছন্দ করেন, যা আমি পছন্দ করি)। কেউ পুরো উত্তরটি পড়বেন বলে আশা করা হচ্ছে
অলিভিয়ার ডুলাক

@ স্টাফেন: "সঠিক জবস্পেক পাওয়া সর্বদা নির্ভরযোগ্যভাবে সম্ভব হয় না": আপনি প্রথমে আউটপুটটি গণনা করতে পারবেন না jobsএবং তখনই জানতে পারবেন যে (এটি আপনার নিজের শেল হিসাবে, তারপরে যা ঘটে তার উপর আপনার নিয়ন্ত্রণ রয়েছে) পরবর্তী পটভূমি চাকরী হবে এন + 1? [তারপরে আপনি এন কে সংরক্ষণ করতে পারেন, এবং পরে% N + 1 কে হত্যা করতে পারেন)
অলিভিয়ার ডুলাক

1
@ অলিভিডারডুলাক, এটি ধরে নেবে যে আপনি কোনও নতুন কাজ শুরু করার পরে (শাঁস পুনরায় কাজের নম্বরগুলি ব্যবহার করবেন) কোনও অতীতের কাজ শেষ হয়নি ated
স্টাফেন চেজেলাস 26'15

28

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

প্রক্রিয়াগুলিকে হত্যা করার একটি বিকল্প নিরাপদ উপায় হ'ল একটি সিউডো-টার্মিনালটিতে আপনার নিয়ন্ত্রণের টিটি সেট করা যার জন্য আপনি মাস্টার পাশের মালিক। তারপরে আপনি টার্মিনালের মাধ্যমে সিগন্যাল প্রেরণ করতে পারেন, উদাহরণস্বরূপ pty এর জন্য SIGTERMবা SIGQUITতার উপরে অক্ষরটি লিখতে ।

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


4
শেলসে কেন এটি করা গেল না তা আমি দেখতে পাচ্ছি না। আমি বেশ কয়েকটি সমাধান দিয়েছি।
স্টাফেন চেজেলাস

3
আপনি দয়া করে বর্ণ উইন্ডোজ এবং অন্যান্য ত্রুটিগুলির একটি ব্যাখ্যা এবং কিছু পরিমাণগত পরিমাণ আলোচনা করতে পারেন? তা ছাড়া, "এখন পর্যন্ত প্রদত্ত সমস্ত উত্তর বগি হিউরিস্টিকস" কোনও সুবিধা ছাড়াই কেবল অযথা সংঘাতমূলক ront
পিটার্ফ

3
@ পেটার্ফ: সাধারণভাবে, পিডের যে কোনও ব্যবহার হ'ল টেকটিউইচ রেস - এটি আপনি যে পদ্ধতিতে উল্লেখ করেছেন এটি একই প্রক্রিয়াটিকে এখনও উল্লেখ করে কিনা তা আপনি যাচাই করেন না কেন, এই প্রক্রিয়াটি উল্লেখ করা এবং কিছু নতুনকে উল্লেখ করা বন্ধ হতে পারে বিরতিতে এটি ব্যবহারের আগে প্রক্রিয়া (সিগন্যাল প্রেরণ)। এটি প্রতিরোধের একমাত্র উপায় হ'ল পিডের মুক্ত / পুনরায় ব্যবহার অবরুদ্ধ করতে সক্ষম হওয়া এবং এটি করতে পারে এমন একমাত্র প্রক্রিয়া হ'ল প্রত্যক্ষ পিতামাতার।
আর ..

2
@ স্টাফেনচাজেলাস: আপনি কীভাবে শেলটিকে সরিয়ে ফেলেছেন এমন একটি পটভূমি প্রক্রিয়াটির পিডিতে অপেক্ষা করতে বাধা দেবেন? যদি আপনি এটি করতে পারেন তবে ওপির প্রয়োজনে সমস্যাটি সহজেই সমাধানযোগ্য।
আর ..

5
@ পিটারফ: "রেস উইন্ডো ছোট" কোনও সমাধান নয়। এবং রেসের বিরলতা অনুক্রমিক পিড কার্যভারের উপর নির্ভরশীল। যে বাগগুলি বছরে একবার খুব খারাপ কিছু ঘটে তার কারণগুলি সমস্ত সময় ঘটে যাওয়া বাগের চেয়ে অনেক খারাপ কারণ সেগুলি সনাক্তকরণ এবং সংশোধন করা কার্যত অসম্ভব।
আর .. 19

10
  1. প্রক্রিয়া আরম্ভ করার সময় তার শুরু সময় সংরক্ষণ করুন:

    longrunningthing &
    p=$!
    stime=$(TZ=UTC0 ps -p "$p" -o lstart=)
    
    echo "Killing longrunningthing on PID $p in 24 hours"
    sleep 86400
    echo Time up!
    
  2. প্রক্রিয়াটি মেরে ফেলার চেষ্টা করার আগে এটি বন্ধ করুন (এটি সত্যই অত্যাবশ্যক নয়, তবে এটি জাতিগত পরিস্থিতি এড়ানোর একটি উপায়: আপনি যদি প্রক্রিয়াটি বন্ধ করেন তবে এটির পিড পুনরায় ব্যবহার করা যাবে না)

    kill -s STOP "$p"
    
  3. দেখুন যে পিআইডি সহ প্রক্রিয়াটির একই শুরু সময় রয়েছে এবং যদি হ্যাঁ, তবে এটি হত্যা করুন, না হলে প্রক্রিয়াটি চালিয়ে যেতে দিন:

    cur=$(TZ=UTC0 ps -p "$p" -o lstart=)
    
    if [ "$cur" = "$stime" ]
    then
        # Okay, we can kill that process
        kill "$p"
    else
        # PID was reused. Better unblock the process!
        echo "long running task already completed!"
        kill -s CONT "$p"
    fi
    

এটি কাজ করে কারণ একই পিআইডি সহ কেবলমাত্র একটি প্রক্রিয়া থাকতে পারে এবং প্রদত্ত ওএসে সময় শুরু করতে পারে ।

চেক চলাকালীন প্রক্রিয়াটি থামানো জাতি-শর্তগুলি একটি অ-ইস্যুতে পরিণত করে। স্পষ্টতই এতে সমস্যা আছে যে, কিছু এলোমেলো প্রক্রিয়া কিছু মিলিসেকেন্ডের জন্য বন্ধ হয়ে যেতে পারে। প্রক্রিয়া ধরণের উপর নির্ভর করে এটি হতে পারে বা কোনও সমস্যা নয়।


ব্যক্তিগতভাবে আমি কেবল অজগর ব্যবহার করতাম এবং psutilযা পিআইডি পুনরায় ব্যবহারের ব্যবস্থা স্বয়ংক্রিয়ভাবে পরিচালনা করে:

import time

import psutil

# note: it would be better if you were able to avoid using
#       shell=True here.
proc = psutil.Process('longrunningtask', shell=True)
time.sleep(86400)

# PID reuse handled by the library, no need to worry.
proc.terminate()   # or: proc.kill()

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

আমি এর আগেও একটি অনুরূপ স্কিম ব্যবহার করেছি (শুরুর সময়টি ব্যবহার করে) তবে আপনার শি স্ক্রিপ্টিং দক্ষতা আমার চেয়ে আরও সুন্দর! ধন্যবাদ।
এফজেএল

এর অর্থ আপনি সম্ভাব্যভাবে ভুল প্রক্রিয়া বন্ধ করছেন। নোট করুন যে ps -o start=ফর্ম্যাটটি কিছুক্ষণ পরে 18:12 থেকে জানুয়ারিতে পরিবর্তিত হবে। পাশাপাশি ডিএসটি পরিবর্তনের বিষয়ে সাবধান থাকুন। যদি লিনাক্সে থাকে তবে আপনি সম্ভবত পছন্দ করবেন TZ=UTC0 ps -o lstart=
স্টাফেন চেজেলাস

@ স্টাফেনচাজেলাস হ্যাঁ, তবে আপনি এটি পরে চালিয়ে যেতে দিয়েছেন। আমি স্পষ্টভাবে বলেছি: এই প্রক্রিয়াটি যে ধরণের কার্য সম্পাদন করছে তার উপর নির্ভর করে আপনার এটি কিছু মিলিসেকেন্ড বন্ধ করার জন্য কিছুটা সমস্যা হতে পারে। lstart
টিপটির

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

7

একটি লিনাক্স সিস্টেমে আপনি নিশ্চয়তা দিতে পারেন যে পিডের পিডের নামস্থানটি জীবিত রেখে পুনরায় ব্যবহার করা হবে না। এটি /proc/$pid/ns/pidফাইলের মাধ্যমে করা যেতে পারে ।

  • man namespaces -

    এই ডিরেক্টরিতে ফাইল ফাইলগুলির মধ্যে একটি বাঁধাই (দেখুন mount(2)) ফাইল সিস্টেমে অন্য কোথাও পিড দ্বারা নির্দিষ্ট প্রক্রিয়াটির সংশ্লিষ্ট নামের স্থানটি জীবিত রাখে যদিও বর্তমানে নামস্থানটিতে সমস্ত প্রক্রিয়া সমাপ্ত হয়।

    এই ডিরেক্টরিতে ফাইলগুলির মধ্যে একটি খুললে (বা এই ফাইলগুলির মধ্যে একটিতে বাঁধা এমন একটি ফাইল) পিড দ্বারা নির্দিষ্ট প্রক্রিয়া সম্পর্কিত নামের জায়গার জন্য একটি ফাইল হ্যান্ডেল দেয়। যতক্ষণ না এই ফাইল বর্ণনাকারী খোলা থাকে, নাম স্থানের সমস্ত প্রক্রিয়া শেষ হয়ে গেলেও, নেমস্পেসটি জীবিত থাকবে। ফাইল বর্ণনাকারী পাস করা যেতে পারে setns(2)

আপনি বিভিন্ন ধরণের প্রক্রিয়া আলাদা করতে পারেন - মূলত যে কোনও সংখ্যক প্রক্রিয়া - এর নাম স্থান রেখে init

  • man pid_namespaces -

    একটি নতুন নামস্থান তৈরি প্রথম প্রক্রিয়া (অর্থাত, প্রক্রিয়া ব্যবহার করে নির্মিত clone(2) সঙ্গে CLONE_NEWPID পতাকা, বা একটি কল পরে একটি প্রক্রিয়া দ্বারা নির্মিত প্রথম সন্তানকে unshare(2)ব্যবহার CLONE_NEWPID পতাকা) করেছে PID, 1 , এবং initনামস্থান জন্য প্রক্রিয়া ( দেখুন init(1)) । নামের জায়গার মধ্যে এতিম হওয়া শিশু প্রক্রিয়াটি এই প্রক্রিয়াটির পরিবর্তে পুনরায় প্রতিস্থাপন করা হবে init(1) (যদি না একই পিআইডি নেমস্পেসে সন্তানের পূর্বপুরুষদের মধ্যে কেউ prctl(2) এআরফিন্ড বংশোদ্ভূত প্রক্রিয়ার রিপার হিসাবে চিহ্নিত হওয়ার জন্য PR_SET_CHILD_SUBREAPER কমান্ড নিযুক্ত না করে)

    যদি initকোনও পিআইডি নেমস্পেসের প্রক্রিয়াটি শেষ হয়ে যায়, কার্নেল একটি সিম্কিল সিগন্যালের মাধ্যমে নেমস্পেসের সমস্ত প্রক্রিয়া বন্ধ করে দেয় । এই আচরণটি পিআইডি নেমস্পেসের initসঠিক ক্রিয়াকলাপের জন্য প্রক্রিয়াটি অপরিহার্য এই বিষয়টি প্রতিফলিত করে ।

util-linuxপ্যাকেজ নামব্যবধান সাধিত জন্য অনেক দরকারী সরঞ্জাম প্রদান করে। উদাহরণস্বরূপ, unshareযদিও, যদি আপনি ইতিমধ্যে কোনও ব্যবহারকারীর নাম-স্থানে এর অধিকারের ব্যবস্থা না করে থাকেন তবে এর জন্য অতিরিক্ত ব্যবহারকারীর অধিকারের প্রয়োজন হবে:

unshare -fp sh -c 'n=
    echo "PID = $$"
    until   [ "$((n+=1))" -gt 5 ]
    do      while   sleep 1
            do      date
            done    >>log 2>/dev/null   &
    done;   sleep 5' >log
cat log; sleep 2
echo 2 secs later...
tail -n1 log

যদি আপনি কোনও ব্যবহারকারীর নেমস্পেসের ব্যবস্থা না করেন তবে আপনি তত্ক্ষণাত সুবিধাগুলি বাদ দিয়ে নিরাপদে নির্বিচার কমান্ডগুলি কার্যকর করতে পারেন। runuserকমান্ড হয় অন্য (অ setuid) দ্বারা উপলব্ধ বাইনারি util-linuxপ্যাকেজ ও এর মত চেহারা হতে পারে একত্রিত:

sudo unshare -fp runuser -u "$USER" -- sh -c '...'

... ইত্যাদি।

উপরের উদাহরণে দুটি স্যুইচ পতাকাটিতে প্রেরণ করা unshare(1)হয়েছে --forkযা অনুরোধ sh -cপ্রক্রিয়াটিকে প্রথম সন্তানের তৈরি এবং তার initস্থিতি নিশ্চিত করে এবং --pidপতাকাটি যা unshare(1)পিডের নামস্থান তৈরি করতে নির্দেশ দেয়।

sh -cপ্রক্রিয়া spawns পাঁচটি পশ্চাদপটে করা শিশু শাঁস - প্রতিটি একটি inifinite whileলুপ যে আউটপুট যোগ অব্যাহত থাকবে dateশেষে logদীর্ঘ হিসাবে হিসাবে জন্য sleep 1সত্য 'ফেরত পাঠায়। এই প্রক্রিয়াগুলিকে প্রসারিত করার পরে অতিরিক্ত 5 সেকেন্ডের জন্য shকল করে sleepতারপরে সমাপ্ত হয়।

এটি সম্ভবত লক্ষণীয় যে -fপতাকাটি যদি ব্যবহার না করা হয় তবে পটভূমিযুক্ত whileলুপগুলির কোনওটিই শেষ হবে না, তবে এটি দিয়ে ...

আউটপুট:

PID = 1
Mon Jan 26 19:17:45 PST 2015
Mon Jan 26 19:17:45 PST 2015
Mon Jan 26 19:17:45 PST 2015
Mon Jan 26 19:17:45 PST 2015
Mon Jan 26 19:17:45 PST 2015
Mon Jan 26 19:17:46 PST 2015
Mon Jan 26 19:17:46 PST 2015
Mon Jan 26 19:17:46 PST 2015
Mon Jan 26 19:17:46 PST 2015
Mon Jan 26 19:17:46 PST 2015
Mon Jan 26 19:17:47 PST 2015
Mon Jan 26 19:17:47 PST 2015
Mon Jan 26 19:17:47 PST 2015
Mon Jan 26 19:17:47 PST 2015
Mon Jan 26 19:17:47 PST 2015
Mon Jan 26 19:17:48 PST 2015
Mon Jan 26 19:17:48 PST 2015
Mon Jan 26 19:17:48 PST 2015
Mon Jan 26 19:17:48 PST 2015
Mon Jan 26 19:17:48 PST 2015
2 secs later...
Mon Jan 26 19:17:48 PST 2015

আকর্ষণীয় উত্তর যা দৃust় বলে মনে হচ্ছে। বুনিয়াদি ব্যবহারের জন্য সম্ভবত কিছুটা ওভারকিল, তবে চিন্তাভাবনা করার মতো।
ইউরিয়েল

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

5

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

  1. একটি সাধারণ মোড়কের স্ক্রিপ্ট যা ব্যাকগ্রাউন্ডে প্রয়োজনীয় কাজ শুরু করবে (alচ্ছিক আউটপুট পুনঃনির্দেশ সহ), একটি ফাইলের মধ্যে এই প্রক্রিয়াটির পিআইডি লিখুন, তারপরে প্রক্রিয়াটি শেষ (অপেক্ষা wait) এবং ফাইলটি অপসারণের জন্য অপেক্ষা করুন। অপেক্ষার সময় যদি প্রক্রিয়াটি মারা যায় যেমন কোনও কিছুর মাধ্যমে

    kill $(cat pidfile)
    

    মোড়ক কেবল পিডফিল সরানো হয়েছে তা নিশ্চিত করবে।

  2. একটি মনিটরের মোড়ক, এটি তার নিজের পিআইডি কোথাও রাখবে এবং এতে প্রেরিত সিগন্যালগুলি ধরে ফেলবে (এবং প্রতিক্রিয়া জানাবে)। সাধারণ উদাহরণ:

    #!/bin/bash
    p=0
    trap killit USR1

    killit () {
        printf "USR1 caught, killing %s\n" "$p"
        kill -9 $p
    }

    printf "monitor $$ is waiting\n"
    therealstuff &
    p=%1
    wait $p
    printf "monitor exiting\n"

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

সাম্প্রতিক (কয়েক বছর বয়সী পড়ুন) লিনাক্স কার্নেলগুলির সাহায্যে সিগ্রুপ , যথা ফ্রিজার ব্যবহার করে এটিকে সুন্দরভাবে চিকিত্সা করা যেতে পারে - যা আমি মনে করি, কিছু আধুনিক লিনাক্স ইন্স সিস্টেম ব্যবহার করে।


ধন্যবাদ, এবং সকলকে। আমি এখনই পড়ছি about মূল কথাটি হ'ল longrunningthingএটি কী তা নিয়ে আপনার কোনও নিয়ন্ত্রণ নেই। আমি একটি শেল স্ক্রিপ্ট উদাহরণও দিয়েছি কারণ এটি সমস্যার ব্যাখ্যা দিয়েছে। আমি আপনার এবং অন্যান্য সমস্ত সৃজনশীল সমাধান এখানে পছন্দ করি তবে আপনি যদি লিনাক্স / ব্যাশ ব্যবহার করেন তবে এর জন্য একটি "সময়সীমা" অন্তর্নির্মিত রয়েছে। আমি মনে করি যে আমার উত্সটি পাওয়া উচিত এবং এটি এটি কীভাবে দেখুন!
এফজেএল

@FJL, timeoutহয় না একটি শেল builtin। timeoutলিনাক্সের জন্য একটি কমান্ডের বিভিন্ন বাস্তবায়ন হয়েছে , সম্প্রতি একটি (জিএনইউ কোর্টিল) (তাই লিনাক্স নির্দিষ্ট নয়) যুক্ত করা হয়েছিল, এবং এটি বর্তমানে বেশিরভাগ লিনাক্স বিতরণ ব্যবহার করে।
স্টাফেন চেজেলাস

@ স্টাফেন - ধন্যবাদ - পরবর্তীকালে আমি জিএনইউ কোর্টিলগুলির উল্লেখ পেয়েছি। তারা বহনযোগ্য হতে পারে, তবে এটি বেস সিস্টেমে না থাকলে এটি নির্ভর করা যায় না। এটি কীভাবে কাজ করে তা জানার জন্য আমি আরও আগ্রহী, যদিও আমি আপনার মন্তব্যটি অন্য কোথাও নোট করেছিলাম যা এটি 100% নির্ভরযোগ্য নয় বলে প্রস্তাব করে। এই থ্রেডটি যেভাবে গেছে তা দিয়ে আমি অবাক হই না!
এফজেএল

1

আপনি যদি লিনাক্সে (এবং কয়েকটি অন্যান্য * নিক্সেস) চালিয়ে যাচ্ছেন তবে আপনি যে মারতে চান সেই প্রক্রিয়াটি এখনও ব্যবহৃত হয়েছে এবং কমান্ড লাইনটি আপনার দীর্ঘ প্রক্রিয়ার সাথে মিলে যায় কিনা তা পরীক্ষা করে দেখতে পারেন । কিছুটা এইরকম :

echo Time up!
grep -q longrunningthing /proc/$p/cmdline 2>/dev/null
if [ $? -eq 0 ]
then
  kill $p
fi

একটি বিকল্প ভালো কিছু সঙ্গে, কতদিন প্রক্রিয়া তোমাকে হত্যা করতে মনস্থ চলমান জন্য চেক করতে হতে পারে ps -p $p -o etime=। আপনি নিজে থেকে এই তথ্যটি বের করে নিজেই করতে পারেন /proc/$p/stat, তবে এটি জটিল হবে (সময়টি জিফিতে মাপা হয়, এবং আপনাকে সিস্টেমটিকে আপটাইমও ব্যবহার করতে হবে /proc/stat)।

যাইহোক, আপনি সাধারণত নিশ্চিত করতে পারবেন না যে আপনার চেকের পরে এবং এটি মারার আগে প্রক্রিয়াটি প্রতিস্থাপন করা হবে না।


এটি এখনও সঠিক নয় কারণ এটি রেসের শর্ত থেকে মুক্তি পায় না।
strcat

@স্ট্রক্যাট প্রকৃতপক্ষে, সাফল্যের কোনও ওয়্যারেন্টি নেই, তবে বেশিরভাগ স্ক্রিপ্টগুলি এমন চেক করতেও বিরক্ত করে না এবং কেবল ফলসই খালি খুন করে cat pidfile। এটি কেবল শেল করে করার কোনও পরিষ্কার উপায়ের কথা আমি মনে করতে পারি না। প্রস্তাবিত নেমস্পেসের উত্তরটি একটি আন্তঃসম্পর্কীয় বলে মনে হচ্ছে ...
ইউরিয়েল

-1

এটি আসলে খুব ভাল প্রশ্ন।

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

সুতরাং, আপনার প্রক্রিয়াটি শুরু করার সাথে সাথেই, md5sum /proc/[pid]/mapsফলাফলটি সংরক্ষণ করুন এবং সংরক্ষণ করুন। পরে আপনি যখন প্রক্রিয়াটি মারতে চান তখন আর একটি এমডি 5সুম করুন এবং এটি তুলনা করুন। যদি এটি মেলে, তবে পিডটি মেরে ফেলুন। যদি না হয়, না।

এটি নিজের জন্য দেখতে, দুটি অভিন্ন বাশ শেল চালু করুন। /proc/[pid]/mapsতাদের জন্য পরীক্ষা করুন এবং আপনি দেখতে পাবেন যে তারা আলাদা। কেন? কারণ এটি একই প্রোগ্রাম হওয়া সত্ত্বেও তারা মেমরিতে বিভিন্ন অবস্থান দখল করে এবং তাদের স্ট্যাকের ঠিকানাগুলি পৃথক। সুতরাং, যদি আপনার প্রক্রিয়াটি মারা যায় এবং এর পিআইডি পুনরায় ব্যবহার করা হয়, এমনকি একই কমান্ডটি একই যুক্তি দিয়ে পুনরায় চালু করা হলেও , "মানচিত্র" ফাইলটি আলাদা হবে এবং আপনি জানতে পারবেন যে আপনি মূল প্রক্রিয়াটি নিয়ে কাজ করছেন না।

: দেখুন proc man পৃষ্ঠা বিস্তারিত জানার জন্য।

নোট করুন যে ফাইলটিতে /proc/[pid]/statইতিমধ্যে অন্যান্য পোস্টারগুলির জবাবগুলির মধ্যে উল্লিখিত সমস্ত তথ্য রয়েছে: প্রক্রিয়াটির বয়স, প্যারেন্ট পিড ইত্যাদি This তুলনার তুলনায়, তারপরে আপনার চালু করার পরে longrunningthing, আপনাকে statফাইলটি থেকে নিম্নলিখিত স্ট্যাটিক ক্ষেত্রগুলি বের করতে হবে এবং পরে তুলনার জন্য সেগুলি সংরক্ষণ করতে হবে:

পিড, ফাইলের নাম, পিড অফ প্যারেন্ট, প্রসেস গ্রুপ আইডি, কন্ট্রোলিং টার্মিনাল, সময় প্রক্রিয়া সিস্টেম বুটের পরে শুরু হয়, আবাসিক সেট আকার, স্ট্যাক শুরুর ঠিকানা,

একসাথে নেওয়া, উপরেরগুলি অনন্যভাবে প্রক্রিয়াটি সনাক্ত করে এবং তাই এটি আরও একটি উপায় উপস্থাপন করে। আসলে আপনি "পিড" এবং "সিস্টেম বুটের পরে সময় প্রক্রিয়া শুরু হয়েছে" ছাড়া উচ্চতর আত্মবিশ্বাসের সাথে আর কিছুই ছাড়তে পারেন না could কেবল statফাইলটি থেকে এই ক্ষেত্রগুলি সরান এবং আপনার প্রক্রিয়া চালু করার পরে এটি কোথাও সংরক্ষণ করুন। পরে এটি হত্যার আগে এটি আবার বের করুন এবং তুলনা করুন। যদি সেগুলি মিলে যায়, তবে আপনি নিশ্চিত হন যে আপনি আসল প্রক্রিয়াটি দেখছেন।


1
/proc/[pid]/mapsঅতিরিক্ত মেমরি বরাদ্দ হওয়ার সাথে সাথে স্ট্যাক বাড়তে থাকে বা নতুন ফাইল ম্যাপ করা হয় তাই সাধারণত সময়ের সাথে সাথে এই পরিবর্তনগুলি কার্যকর হয় না ... এবং আরম্ভ করার পরে অবিলম্বে এর অর্থ কী? সব লাইব্রেরির পরে মানচিত্র তৈরি হয়েছে? তা তুমি কিভাবে নির্ধারণ কর?
স্টাফেন চেজেলাস

আমি এখন দুটি সিস্টেমে আমার সিস্টেমে একটি পরীক্ষা করছি, একটি জাভা অ্যাপ এবং অন্যটি সিফিনজিন সার্ভার। প্রতি 15 মিনিটে আমি md5sumতাদের মানচিত্রের ফাইলগুলিতে করি। আমি এটি এক বা দুই দিনের জন্য চালিয়ে দেব এবং ফলাফলগুলি দিয়ে এখানে এখানে প্রতিবেদন করব।
মাইকেল মার্টিনেজ

@ স্টাফেনচাজেলাস: আমি এখন আমার 16 ঘন্টা ধরে আমার দুটি প্রক্রিয়া পরীক্ষা করে দেখছি, এবং এমডি 5সুমে কোনও পরিবর্তন হয়নি
মাইকেল মার্টিনেজ

-1

আর একটি উপায় হ'ল প্রক্রিয়াটি হত্যার আগে তার বয়স পরীক্ষা করা। এইভাবে, আপনি নিশ্চিত করতে পারেন যে আপনি এমন কোনও প্রক্রিয়া মারা যাচ্ছেন না যা 24 ঘন্টােরও কম সময়ে তৈরি হয়নি। ifপ্রক্রিয়াটি হত্যার আগে আপনি তার ভিত্তিতে একটি শর্ত যুক্ত করতে পারেন ।

if [[ $(ps -p $p -o etime=) =~ 1-. ]] ; then
    kill $p
fi

এই ifশর্তটি প্রক্রিয়া আইডি $p24 ঘন্টা (86400 সেকেন্ড) এর চেয়ে কম কিনা তা পরীক্ষা করবে ।

PS: - কমান্ডটির ps -p $p -o etime=ফর্ম্যাট থাকবে<no.of days>-HH:MM:SS


mtimeএর /proc/$pপ্রক্রিয়া শুরুর সময় সঙ্গে কিছুই করার আছে।
স্টাফেন চেজেলাস

ধন্যবাদ @ স্টাফেনচাজেলাস। তুমি ঠিক. ifশর্ত পরিবর্তন করতে আমি উত্তর সম্পাদনা করেছি । যদি এটি বাগী হয় তবে বিনা দ্বিধায় মন্তব্য করুন।
শ্রী

-3

আমি যা করি তা হল প্রক্রিয়াটি মেরে ফেলার পরে এটি আবার করুন। প্রতিবার যখনই করি তখনই উত্তরটি ফিরে আসে, "এরকম কোনও প্রক্রিয়া নেই"

allenb   12084  5473  0 08:12 pts/4    00:00:00 man man
allenb@allenb-P7812 ~ $ kill -9 12084
allenb@allenb-P7812 ~ $ kill -9 12084
bash: kill: (12084) - No such process
allenb@allenb-P7812 ~ $ 

সহজ হতে পারে না এবং আমি বহু বছর ধরে এটি কোনও সমস্যা ছাড়াই করে চলেছি।


এটি "কীভাবে আমি এটি ঠিক করতে পারি" নয়, "আমি কীভাবে এটি আরও খারাপ করতে পারি" প্রশ্নের উত্তর দিচ্ছি।
স্টাফেন চেজেলাস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.