কীভাবে সবে শুরু করা প্রক্রিয়াটির প্রশ্রয় পাবেন


70

আমি প্রক্রিয়াটি শুরু করতে চাই (উদাঃ মাইকম্যান্ড) এবং এর পিড পেতে (এটি পরে হত্যা করার অনুমতি দেওয়ার জন্য)।

আমি পিএস চেষ্টা করেছি এবং নাম অনুসারে ফিল্টার করেছি, তবে নাম দিয়ে প্রক্রিয়া আলাদা করতে পারছি না

myCommand
ps ux | awk '/<myCommand>/ {print $2}' 

কারণ প্রক্রিয়াগুলির নামগুলি অনন্য নয়।

আমি এর দ্বারা প্রক্রিয়া চালাতে পারি:

myCommand &

আমি দেখতে পেয়েছি যে আমি এই পিআইডি পেতে পারি:

echo $!

কোন সহজ সমাধান আছে?

আমি আমার কম্যান্ড কার্যকর করতে এবং এক লাইনের কমান্ডের ফলে এর পিআইডি পেতে পেরে খুশি হব।

উত্তর:


77

এর চেয়ে সহজ আর কী হতে পারে echo $!? এক লাইন হিসাবে:

myCommand & echo $!

"এবং" এর সাহায্যে এই আদেশগুলি মার্জ করার জন্য আপনাকে ধন্যবাদ।
রাফালমাগ

8
বাশ স্ক্রিপ্টে, একটি লুপে যা প্রোগ্রাম শুরু করে, $! সঠিক নয়। কখনও কখনও এটি স্ক্রিপ্টের পিড নিজেই ফেরত দেয়, কখনও কখনও গ্রেপ বা অ্যাডাব্লিক স্ক্রিপ্ট থেকে চালিত করে নির্দিষ্টভাবে এই দৃশ্যে প্রবর্তিত প্রক্রিয়াটির পিড পাওয়ার কোনও সমাধান হয়? myprogram

2
এনবি এটির জন্য আপনাকে &পূর্ববর্তী লাইন হিসাবে কমান্ডটি শুরু করতে হবে , অন্যথায় প্রতিধ্বনিটি মূলত ফাঁকা ফিরে আসে।
রজারডপ্যাক

2
ভেরিয়েবলের মতো command & echo $!কার্যনির্বাহীকরণ এই পদক্ষেপে মৃত্যুদণ্ড স্থির করে দেয় :(
শশাঙ্ক বিবেক

26

একটি ছোট স্ক্রিপ্টে কমান্ডটি মোড়ানো করুন

#!/bin/bash
yourcommand &
echo $! >/path/to/pid.file

20

আপনি ব্যবহার করতে পারেন sh -cএবং execকমান্ডের পিআইডি এটি চালানোর আগেই পেতে পারেন ।

শুরু করতে myCommand, যাতে এটির চালনা শুরু হওয়ার আগে এর পিআইডি মুদ্রিত হয়, আপনি এটি ব্যবহার করতে পারেন:

sh -c 'echo $$; exec myCommand'

কিভাবে এটা কাজ করে:

এটি একটি নতুন শেল শুরু করে, সেই শেলের পিআইডি প্রিন্ট করে এবং তারপরে একই পিআইডি রয়েছে তা নিশ্চিত করে আপনার কমান্ড দিয়ে শেলটি প্রতিস্থাপন করতে execবিল্টিন ব্যবহার করে । আপনার শেল সঙ্গে একটি কমান্ড রান যখন builtin, আপনার শেল হয় আসলে হয়ে যে কমান্ড বদলে আরো সাধারণ আচরণ নিজেই একটি নতুন অনুলিপি, যা তার নিজস্ব পৃথক PID, এবং যা পরে কমান্ড হয়ে forking করুন।exec

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

এই উত্তরের মধ্যে এই কৌশলটির একটি উদাহরণ রয়েছে।


এই কমান্ডের কিছু অংশ মাঝেমধ্যে বাদ দেওয়া যেতে পারে, তবে সাধারণত হয় না।

এমনকি আপনি যে শেলটি ব্যবহার করছেন তা বোর্ন-স্টাইল এবং execএই শব্দার্থকগুলির সাহায্যে বিল্টিনকে সমর্থন করলেও , সাধারণত আপনি এই উদ্দেশ্যে sh -cএকটি নতুন, পৃথক শেল প্রক্রিয়া তৈরি করতে (বা সমতুল্য) ব্যবহার এড়াতে চেষ্টা করবেন না কারণ:

  • শেলটি একবার হয়ে গেলে myCommand, পরবর্তী কমান্ডগুলি চালানোর জন্য কোনও শেল অপেক্ষা করে না। নিজেকে প্রতিস্থাপনের পরে sh -c 'echo $$; exec myCommand; fooচালানোর চেষ্টা করতে সক্ষম হবে না । আপনি যদি কোনও স্ক্রিপ্ট না লিখেন যা এটিকে এটির শেষ কমান্ড হিসাবে চালিত করে, আপনি কেবল শেলটি ব্যবহার করতে পারবেন না যেখানে আপনি অন্যান্য কমান্ডগুলি চালাচ্ছেন।foomyCommandecho $$; exec myCommand
  • আপনি এটির জন্য সাবসেল ব্যবহার করতে পারবেন না । (echo $$; exec myCommand)সিনট্যাক্টিকালি এর চেয়ে সুন্দর হতে পারে sh -c 'echo $$; exec myCommand'তবে আপনি যখন $$ভিতরে চলে যান তখন ( )এটি প্যারেন্ট শেলের পিআইডি দেয়, সাবসেল নিজেই নয়। তবে এটি সাবসেলের পিআইডি হ'ল নতুন কমান্ডের পিআইডি। কিছু শেল সাবসেলের পিআইডি সন্ধানের জন্য তাদের নিজস্ব অ-বহনযোগ্য ব্যবস্থা সরবরাহ করে, যা আপনি এটির জন্য ব্যবহার করতে পারেন। বিশেষত, বাশ 4 এ , (echo $BASHPID; exec myCommand)কাজ করে।

পরিশেষে, নোট করুন যে কয়েকটি শেলগুলি একটি অপ্টিমাইজেশন সম্পাদন করবে যেখানে তারা একটি কমান্ড execচালিয়ে যায় যেমন (যেমন, তারা প্রথমে কাঁটাচামচ ভুলে যায়) যখন জানা যায় যে শেলটি পরে কিছু করার প্রয়োজন হবে না। কিছু শেল যেকোন সময় এটি করার চেষ্টা করে এটি চালানো শেষ কমান্ড হয়, অন্যরা কেবল তখনই তা করতে পারে যখন কমান্ডের আগে বা পরে কোনও কমান্ড না থাকে এবং অন্যরা এটি কিছু করবে না। প্রভাব যদি আপনার লেখার জন্য ভুলে যাবেন না যে হয় execএবং মাত্র ব্যবহার sh -c 'echo $$; myCommand'তারপর এটি হবে কখনও কখনও উপর ডান PID, দিতে কিছু সহ সিস্টেমের কিছু শাঁস। আমি কখনও এই জাতীয় আচরণের উপর নির্ভর করার বিরুদ্ধে সুপারিশ করি এবং এর পরিবর্তে সর্বদা আপনার execযখন প্রয়োজন তা অন্তর্ভুক্ত করুন।


আমি চালানোর আগে myCommand, আমার বাশ স্ক্রিপ্টে আমাকে বেশ কয়েকটি পরিবেশের ভেরিয়েবল সেট করা দরকার। execকমান্ডটি চালাচ্ছে এমন পরিবেশে কি এগুলি চালিত হবে?
ব্যবহারকারীর 35359531

দেখে মনে হচ্ছে আমার পরিবেশ execকমান্ডের মধ্যে চলেছে । যাইহোক, myCommandঅন্যান্য প্রক্রিয়াগুলি শুরু করার সময় এই পদ্ধতিটি কার্যকর হয় না , যা আপনার সাথে কাজ করা দরকার are যখন আমি ইস্যু একটি kill -INT <pid>যেখানে pidএই ভাবে প্রাপ্ত হয়েছিল, সিগন্যাল উপ-প্রসেস পৌঁছায় না শুরু myCommand, যেহেতু আমি যদি চালানো myCommand বর্তমান সেশন এবং Ctrl + সি, সংকেত সঠিকভাবে সঞ্চারিত।
ব্যবহারকারীর 35359531

1
আমি এটি চেষ্টা করেছি, তবে মাইকম্যান্ড প্রক্রিয়াটির পিড ইকো $$ +1 দ্বারা পিড আউটপুট বলে মনে হচ্ছে। আমি কি ভুল কিছু করছি?
ক্রোবার

আমার কমান্ডটি এর মতো দেখাচ্ছে:sh -c 'echo $$; exec /usr/local/bin/mbdyn -f "input.file" -o "/path/to/outputdir" > "command_output.txt" 2>&1 &'
ক্রোবার

7

আমি কোনও সহজ সমাধান জানি না, তবে $ ব্যবহার করছি না! যথেষ্ট? অন্যদের মতামত অনুসারে আপনি যদি প্রয়োজন হয় তবে কিছু অন্যান্য পরিবর্তনশীলকে সর্বদা মান নির্ধারণ করতে পারেন।

পার্শ্ব নোট হিসাবে, পিএস থেকে পাইপ না করে আপনি ব্যবহার করতে পারেন pgrepবা pidof


5

একটি ফাইলটিতে পিড নিবন্ধনের পরে বাশ স্ক্রিপ্ট থেকে এক্সিকিউট ব্যবহার করুন:

উদাহরণ:

ধরুন আপনার কাছে "চিরতরে.শ" নামে একটি স্ক্রিপ্ট রয়েছে যা আপনি পি 1, পি 2, পি 3 দিয়ে চালাতে চান

চিরকালের জন্য। সোর্সকোড:

#!/bin/sh

while [ 1 -lt 2 ] ; do
    logger "$0 running with parameters \"$@\""
    sleep 5
done

একটি reaper.sh তৈরি করুন:

#!/bin/sh

echo $$ > /var/run/$1.pid
exec "$@"

চিরদিনের জন্য চালান।

./reaper.sh ./forever.sh p1 p2 p3 p4 &

সর্বদা.শ প্রতি 5 সেকেন্ডে সিসলোগে লাইন লগ করা ছাড়া আর কিছুই করে না

আপনার এখন /var/run/forever.sh.pid এ পিড রয়েছে

cat /var/run/forever.sh.pid 
5780

এবং চিরকালের জন্য সিসলগ গ্রেপ:

Nov 24 16:07:17 pinkpony cia: ./forever.sh running with parameters "p1 p2 p3 p4"

আপনি এটি প্রক্রিয়া সারণিতে দেখতে পারেন:

ps axuwww|grep 'forever.sh p1' |grep -v grep
root      5780  0.0  0.0   4148   624 pts/7    S    16:07   0:00 /bin/sh ./forever.sh p1 p2 p3 p4

3
উহু, এবং "oneliner" দিনঃ / bin / SH -c 'প্রতিধ্বনি $$> / tmp /' my.pid && Exec প্রোগ্রাম args '&
user237419

1
আর্গুমেন্টে অভ্যন্তরীণ সাদা স্থানটি সঠিকভাবে সংরক্ষণ করতে, আপনার exec "$@"পরিবর্তে ব্যবহার করা উচিত exec $*। প্রযুক্তিগতভাবে আপনার যা সংরক্ষণ করতে হবে তা হ'ল স্পেস নয় বরং আইএফএস শেল প্যারামিটারের অক্ষরগুলির উপস্থিতি (যা স্থান, ট্যাব এবং নিউলাইনে ডিফল্ট হবে)।
ক্রিস জনসন

পয়েন্ট নেওয়া। :)
ব্যবহারকারী 237419

ধন্যবাদ, আমি $$ প্যারামিটারটি জানতাম না। এটি খুব দরকারী হতে পারে।
রাফালমাগ

3

বাশ শেলের $!মধ্যে jobs -pবিল্ট-ইন হতে পারে এর বিকল্প । কিছু কিছু ক্ষেত্রে !$!আগে (অথবা পরিবর্তে) পরিবর্তনশীল সম্প্রসারণ শেল ব্যাখ্যা পরার, অপ্রত্যাশিত ফলাফল সৃষ্টি করে।

উদাহরণস্বরূপ, এটি কাজ করবে না:

((yourcommand) & echo $! >/var/run/pidfile)

যখন এটি করবে:

((yourcommand) & jobs -p >/var/run/pidfile)

আমি মনে করি আপনি বোঝাতে চেয়েছিলেন ((আপনার কম্যান্ড)) এবং জবস -p> / ভার / রান / পিডফাইল)।
ডোম

1

আপনি এর মতো কিছু ব্যবহার করতে পারেন:

$ myCommand ; pid=$!

অথবা

$ myCommand && pid=$!

দুটি কমান্ড ব্যবহার করে ;বা জয়েন্টগুলি হতে পারে &&। দ্বিতীয় ক্ষেত্রে, প্রথম কমান্ড সফল হলেই পিড সেট করা হবে। আপনি প্রক্রিয়া আইডি পেতে পারেন $pid


3
ওপি পিআইডি পেতে চায় যাতে সে পরে এটি মেরে ফেলতে পারে। ; এবং && এর প্রতিধ্বনি হওয়ার পূর্বে মূল প্রক্রিয়াটি প্রস্থান করার প্রয়োজন $ মৃত্যুদন্ড কার্যকর করা হয়
ব্যবহারকারী 9517

হ্যাঁ তুমিই ঠিক. এটি মাইকম্যান্ড বন্ধ হয়ে যাওয়ার পরে আপনাকে পিড দেবে।
খালেদ

6
কমান্ড বিভাজকের বাম-হাতের জন্য শুরু হওয়া প্রক্রিয়াটির পিআইডি বা $!পরে আপনাকে উল্লেখ করবে না। কেবলমাত্র অ্যাসিক্রোনাকলভাবে প্রসেস করা প্রসেসগুলির জন্য সেট করা থাকে (উদাহরণস্বরূপ সাধারণত তবে কিছু শেলের অন্যান্য পদ্ধতিও থাকে)। &&;$!&
ক্রিস জনসেন

এটি সহায়ক, এবং কেন আমাকে বাদ দিয়ে কেউ ভোট দেয় না? যদিও ভাল কাজ :)
মন্দির

1

এটি হ্যাক-ওয়াই উত্তর এবং এটি সম্ভবত বেশিরভাগ মানুষের পক্ষে কার্যকর হবে না। এটি একটি বিশাল সুরক্ষা ঝুঁকিপূর্ণ মিথথিক্স, সুতরাং আপনি নিরাপদ থাকবেন এবং ইনপুটগুলি স্যানিটাইজড করা হবে এবং ... ভাল, আপনি ধারণাটি পেয়েছেন না তবে এটি করবেন না।

ছোট্ট সি প্রোগ্রামটি এখানে বাইনারি start(বা আপনি যা চান) তে কম্পাইল করুন , তারপরে আপনার প্রোগ্রামটি চালান./start your-program-here arg0 arg1 arg2 ...

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    if (argc >= 2)
    {
        printf("%lu\n", (long unsigned) getpid());
        if (execvp(argv[1], &argv[1]) < 0)
        {
            perror(NULL);
            return 127;
        }
    }
    return 0;
}

দীর্ঘ গল্প সংক্ষিপ্ত, এটি পিআইডি প্রিন্ট করবে stdout, তারপরে আপনার প্রোগ্রামটি প্রক্রিয়ায় লোড করবে। এটি এখনও একই পিআইডি থাকা উচিত।


ব্যাশ ভেরিয়েবলের মধ্যে এই কোডটি দিয়ে ফিরে আসা পিআইডি নম্বরটি কীভাবে রেকর্ড করব? আমার কাছে অস্পষ্ট কারণ হিসাবে, stdoutএই উদাহরণে লিপিবদ্ধ বলে মনে হচ্ছে না:RESULT="$(./start_and_get_pid.out echo yo)"; echo "$RESULT"
Tfb9

@ টিএফবি 9: আমি সত্যিই অন্য পদ্ধতির একটির প্রস্তাব দিই; আমি এটি 2+ বছর আগে লিখেছিলাম এবং এটি হ্যাকিয়ার / ত্রুটি-প্রবণ পদ্ধতিগুলির মধ্যে এখনও পর্যন্ত উপস্থাপিত হয়েছে (বা তাই আমি মনে করি)।
টোনিসডজি

নোটের জন্য ধন্যবাদ। আমি মনে করি আমি এটি দিয়ে আমার সমস্যাটি সমাধান করেছিsleep 10 & PID_IS=$!; echo $PID_IS
Tfb9
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.