পিএইচপি-তে অ্যাসিঙ্ক্রোনাস শেল এক্সিকিউটিভ


199

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

আমি বিভিন্ন দিকে তাকালেন থাকেন exec(), shell_exec(), pcntl_fork(), ইত্যাদি ফাংশন, কিন্তু তাদের কেউ ঠিক আমি কি চাই অফার বলে মনে হচ্ছে। (বা, যদি তারা করেন তবে তা আমার কাছে পরিষ্কার নয় কীভাবে)) কোনও পরামর্শ?


কোন ব্যাপার যা সমাধান আপনার চয়ন করা, এছাড়াও আপনি ব্যবহার বিবেচনা করা উচিত niceএবং ioniceআপনার সিস্টেম (যেমন অপ্রতিরোধ্য থেকে শেল স্ক্রিপ্ট প্রতিরোধ /usr/bin/ionice -c3 /usr/bin/nice -n19)
rinogo

উত্তর:


218

যদি এটি "আউটপুটটির বিষয়ে চিন্তা করে না", তবে স্ক্রিপ্টটিতে নির্বাহকারীকে &প্রক্রিয়াটির ব্যাকগ্রাউন্ড দিয়ে ডাকা যাবে না?

সম্পাদনা - @ অ্যাডাম দ্য হট এই পোস্টে কি মন্তব্য করেছে তা অন্তর্ভুক্ত করে আপনি এটিকে এই কলটিতে যোগ করতে পারেন exec:

" > /dev/null 2>/dev/null &"

এটি ব্যাকগ্রাউন্ডে stdio(প্রথম >) এবং stderr( 2>) উভয়ই পুনর্নির্দেশ করবে /dev/null

একই জিনিসটি করার অন্যান্য উপায় রয়েছে তবে এটি পড়ার সবচেয়ে সহজ।


উপরের ডাবল-রিডাইরেক্টর বিকল্প:

" &> /dev/null &"

11
এটি কাজ করে বলে মনে হচ্ছে তবে এম্পারস্যান্ডের চেয়ে কিছুটা বেশি প্রয়োজন। এক্সিকিউটর () কলটিতে "> / dev / null 2> / dev / null &" যুক্ত করে আমি এটি কাজ করেছিলাম। যদিও আমাকে স্বীকার করতে হবে আমি তা নিশ্চিত কি না what
অ্যাডামহট্ট

2
আপনি আগুন চাইলে অবশ্যই যাওয়ার উপায় এবং পিএইচপি এবং অ্যাপাচি দিয়ে ভুলে যান। প্রচুর উত্পাদন অ্যাপাচি এবং পিএইচপি পরিবেশে pcntl_fork () অক্ষম থাকবে।
পদ্ধতি 21

9
এর জন্য কেবল একটি নোট &> /dev/null &, আপনি যদি এটি ব্যবহার করেন তবে xdebug লগ তৈরি করে না। চেক stackoverflow.com/questions/4883171/...
kapeels

5
@ মিশেল জে মুলিগান এটি ফাইল বর্ণনাকারীদের বন্ধ করে দেয়। এটি বলেছিল, দক্ষতা অর্জন সত্ত্বেও, অনড় দৃষ্টিতে, ব্যবহার /dev/nullকরা আরও ভাল অনুশীলন, কারণ বন্ধ করা এফডিগুলিতে লেখাই ত্রুটির কারণ হয়ে দাঁড়ায়, অন্যদিকে /dev/nullচুপচাপ কিছু পড়ার বা লেখার চেষ্টা করার ফলে কিছুই হয় না।
চার্লস ডাফি

3
অ্যাপাচি পুনঃসূচনা করার সময় পটভূমি স্ক্রিপ্টগুলি হত্যা করা হবে ... খুব দীর্ঘ কাজের জন্য এই বিষয়ে সচেতন থাকুন বা যদি আপনি দুর্ভাগ্য সময়জ্ঞানসম্মত হন এবং আপনি কেন আপনার কাজটি অদৃশ্য হয়ে যায় তা ভাবছেন ...
জুলিয়ান

53

আমি ব্যবহৃত , এই জন্য এটি সত্যিই একটি স্বাধীন প্রক্রিয়া শুরু হয়।

<?php
    `echo "the command"|at now`;
?>

4
কিছু পরিস্থিতিতে এটি একেবারে সেরা সমাধান। ওয়েবগুই থেকে একটি "সুডো রিবুট" ("ইকো 'স্লিপ 3; সুডো রিবুট' | এখন") প্রকাশ করার জন্য এটিই আমার পক্ষে কাজ করেছিল এবং ওপেনবিএসে
কাই

1
আপনি যদি আপাচি চালান (সাধারণত www-data) ব্যবহারকারীর ব্যবহারের অনুমতি না থাকে atএবং আপনি এটির জন্য কনফিগার করতে না পারেন <?php exec('sudo sh -c "echo \"command\" | at now" ');তবে আপনি ব্যবহারের চেষ্টা করতে পারেন যদি commandউদ্ধৃতিগুলি থাকে, আপনার মাথাব্যথা বাঁচাতে এস্কেপশালার্গ দেখুন
জুলিয়েন

1
এটি সম্পর্কে ভালভাবে চিন্তা করা, sh চালানোর জন্য sudo পাওয়া ভাল ধারণা নয়, কারণ এটি মূলত সুডোকে সমস্ত কিছুতে একটি রুট অ্যাক্সেস দেয়। আমি ব্যবহার রূপে ফিরিয়ে echo "sudo command" | at nowএবং মন্তব্য www-dataআউট/etc/at.deny
জুলিয়েন

@ জুলিয়েন সম্ভবত আপনি sudo কমান্ড দিয়ে একটি শেল স্ক্রিপ্ট তৈরি করতে পারেন এবং তার পরিবর্তে এটি চালু করতে পারেন। যতক্ষণ না আপনি কোনও ব্যবহারকারীর জমা দেওয়া মানগুলিকে স্ক্রিপ্টে জমা দিচ্ছেন না
গ্রেট ক্লোর্ন

26

সমস্ত উইন্ডোজ ব্যবহারকারীদের কাছে: আমি একটি অ্যাসিনক্রোনাস পিএইচপি স্ক্রিপ্ট চালানোর জন্য একটি ভাল উপায় খুঁজে পেয়েছি (আসলে এটি প্রায় সব কিছু নিয়ে কাজ করে)।

এটি popen () এবং pclose () কমান্ডের উপর ভিত্তি করে। এবং উইন্ডোজ এবং ইউনিক্স উভয়ই ভাল কাজ করে।

function execInBackground($cmd) {
    if (substr(php_uname(), 0, 7) == "Windows"){
        pclose(popen("start /B ". $cmd, "r")); 
    }
    else {
        exec($cmd . " > /dev/null &");  
    }
} 

আসল কোড থেকে: http://php.net/manual/en/function.exec.php#86329


এটি কেবল একটি ফাইল কার্যকর করে, পিএইচপি / পাইথন / নোড ইত্যাদি ব্যবহার করে কাজ করে না
ডেভিড ভ্যালেন্টিনো

@ ডেভিডভ্যালেন্টিনো সঠিক, এবং এটি ঠিক আছে! আপনি যদি কোনও পিএইচপি / পাইথন / নোডজেএস স্ক্রিপ্ট সম্পাদন করতে চান তবে আপনাকে অবশ্যই এক্সিকিউটেবলকে কল করতে হবে এবং এতে আপনার স্ক্রিপ্টটি দিতে হবে। উদাহরণস্বরূপ: আপনি আপনার টার্মিনালে রাখবেন না myscript.jsতবে পরিবর্তে আপনি লিখবেন node myscript.js। এটি হ'ল: নোড হল এক্সিকিউটেবল, myscript.js হ'ল কার্যকর, ভাল স্ক্রিপ্ট। এক্সিকিউটেবল এবং স্ক্রিপ্টের মধ্যে একটি বিশাল পার্থক্য রয়েছে।
লুকাকাম

অধিকার না না যে ক্ষেত্রে কোন সমস্যা নেই ,, প্রয়োজন মত অন্যান্য ক্ষেত্রে উদাহরণে Laravel শিল্পী, চালানোর জন্য php artisanশুধু করা মন্তব্য এখানে এত কোন প্রয়োজন কমান্ড দিয়ে কেন এটা অভ্যস্ত কাজ ট্রেসিং
ডেভিড Valentino

22

লিনাক্সে আপনি নিম্নলিখিতগুলি করতে পারেন:

$cmd = 'nohup nice -n 10 php -f php/file.php > log/file.log & printf "%u" $!';
$pid = shell_exec($cmd);

এটি কমান্ড প্রম্প্টিতে কমান্ডটি কার্যকর করবে এবং তারপরে কেবল পিআইডি ফিরিয়ে দেবে, যা আপনি এটি পরীক্ষা করে দেখতে 0> পরীক্ষা করতে পারেন।

এই প্রশ্নটি একই: পিএইচপি এর থ্রেডিং আছে?


আপনি যদি কেবল খালি প্রয়োজনীয় জিনিসগুলি ( action=generate var1_id=23 var2_id=35 gen_id=535বিভাগটি বাদ দিয়ে ) অন্তর্ভুক্ত করেন তবে এই উত্তরটি পড়া সহজ হবে । এছাড়াও, যেহেতু ওপি শেল স্ক্রিপ্ট চালানোর বিষয়ে জিজ্ঞাসা করেছে, আপনার পিএইচপি-নির্দিষ্ট অংশের প্রয়োজন নেই। চূড়ান্ত কোডটি হবে:$cmd = 'nohup nice -n 10 /path/to/script.sh > /path/to/log/file.log & printf "%u" $!';
রিনোগো

এছাড়াও, "আগে সেখানে ছিলেন" এমন একজনের একটি নোট হিসাবে, যে কেউ এটি পড়ছেন কেবল সেগুলি নয় niceবরং এটি ব্যবহার করা বিবেচনা করতে পারে ionice
রিনোগো

1
"% U" What কী করে! ঠিক কি?
টুইগস

@ টিভিগস &ব্যাকগ্রাউন্ডে পূর্ববর্তী কোড চালায়, তারপরে ভেরিয়েবলের printfবিন্যাসিত আউটপুট ব্যবহার করা $!হয় যা পিআইডি
NoChecksum

1
আপনাকে অনেক ধন্যবাদ, আমি অ্যাসিঙ্ক পিএইচপি শেল কল সহ একটি লগটিতে আউটপুট বের করার জন্য আমি সমস্ত প্রকারের সমাধানের চেষ্টা করেছি এবং মানদণ্ডগুলির সমস্তটি পূরণ করে এমন একমাত্র আপনার।
জোশ পাওলিসন


6

লিনাক্সে, আপনি কমান্ডের শেষে একটি অ্যাম্পারস্যান্ড যুক্ত করে একটি নতুন স্বাধীন থ্রেডে একটি প্রক্রিয়া শুরু করতে পারেন

mycommand -someparam somevalue &

উইন্ডোজে আপনি "স্টার্ট" ডস কমান্ডটি ব্যবহার করতে পারেন

start mycommand -someparam somevalue

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

1
startউইন্ডোতে কমান্ড পরীক্ষা করা হয়েছে , এটি তাত্পর্যপূর্ণভাবে চলবে না ... আপনি যে উত্স থেকে এই তথ্যটি পেয়েছেন তা উত্সকে অন্তর্ভুক্ত করতে পারবেন?
আলফ.দেব

: @ Alph.Dev দয়া করে আপনি Windows ব্যবহার করছেন আমার উত্তর করার জন্য একটি কটাক্ষপাত stackoverflow.com/a/40243588/1412157
LucaM

@ মাইনেমিস আপনার উত্তরটি সূচিত কমান্ড কেন কাজ করছে না তা ঠিক তা দেখায়। এটি /Bপ্যারামিটারের কারণে । : আমি তা এখানে ব্যাখ্যা করে থাকেন stackoverflow.com/a/34612967/1709903
Alph.Dev

6

এটি করার সঠিক উপায় (!)

  1. কাঁটাচামচ ()
  2. setsid ()
  3. execve ()

কাঁটাচামচ কাঁটাচামচ, সেটিড বর্তমান প্রক্রিয়াটিকে মাস্টার ওয়ান (কোনও পিতামাতা নয়) হওয়ার জন্য বলুন, কলিং প্রক্রিয়াটিকে কলটি দ্বারা প্রতিস্থাপন করতে বলুন। যাতে পিতামাতারা সন্তানের উপর প্রভাব না ফেলেই চলে যেতে পারেন।

 $pid=pcntl_fork();
 if($pid==0)
 {
   posix_setsid();
   pcntl_exec($cmd,$args,$_ENV);
   // child becomes the standalone detached process
 }

 // parent's stuff
 exit();

6
Pcntl_fork () এর সমস্যাটি হ'ল এটি একটি ওয়েব সার্ভারের অধীনে চলাকালীন আপনার এটি ব্যবহার করার কথা নয়, যেমনটি ওপি করে (পাশাপাশি, ওপি ইতিমধ্যে এটি চেষ্টা করেছে)।
গাস

6

আমি এটি ব্যবহার করেছি ...

/** 
 * Asynchronously execute/include a PHP file. Does not record the output of the file anywhere.  
 * Relies on the PHP_PATH config constant.
 *
 * @param string $filename  file to execute
 * @param string $options   (optional) arguments to pass to file via the command line
 */ 
function asyncInclude($filename, $options = '') {
    exec(PHP_PATH . " -f {$filename} {$options} >> /dev/null &");
}

(যেখানে PHP_PATHকনস্টের মত define('PHP_PATH', '/opt/bin/php5')বা অনুরূপ সংজ্ঞা দেওয়া হয়েছে )

এটি কমান্ড লাইনের মাধ্যমে তর্কগুলিতে যায়। এগুলি পিএইচপি-তে পড়তে, আরজিভি দেখুন


4

সত্যিকার অর্থে আমার পক্ষে কাজ করার একমাত্র উপায় হ'ল:

shell_exec('./myscript.php | at now & disown')

3
'অস্বীকার' বাশ অন্তর্নির্মিত এবং শেল_এক্সেক () এর সাথে এইভাবে কাজ করে না। আমি চেষ্টা করেছি shell_exec("/usr/local/sbin/command.sh 2>&1 >/dev/null | at now & disown")এবং যা কিছু পেয়েছি তা হ'ল:sh: 1: disown: not found
টমাস দাগার্ড

4

আমি এর জন্য সিমফনি প্রক্রিয়া উপাদানটিও দরকারী বলে মনে করি ।

use Symfony\Component\Process\Process;

$process = new Process('ls -lsa');
// ... run process in background
$process->start();

// ... do other things

// ... if you need to wait
$process->wait();

// ... do things after the process has finished

এটির গিটহাব রেপোতে এটি কীভাবে কাজ করে তা দেখুন ।


2
সতর্কতা: আপনি যদি অপেক্ষা না করেন, অনুরোধটি শেষ হয়ে গেলে প্রক্রিয়াটি মারা যাবে
the_nuts

পারফেক্ট টুল, এটি proc_*অভ্যন্তরীণ ফাংশনগুলির উপর ভিত্তি করে ।
MAChitgarha


1

একটি নামযুক্ত ফিফো ব্যবহার করুন।

#!/bin/sh
mkfifo trigger
while true; do
    read < trigger
    long_running_task
done

তারপরে আপনি যখনই দীর্ঘকালীন চলমান কার্য শুরু করতে চান, কেবল একটি নতুন লাইন লিখুন (ট্রিগার ফাইলটিতে অবরুদ্ধ)।

আপনার ইনপুট যতক্ষণ না ছোট হয় PIPE_BUFএবং এটি একক write()ক্রিয়াকলাপ হয় ততক্ষণ আপনি ফিফোতে যুক্তি লিখতে পারেন এবং $REPLYস্ক্রিপ্টের মতো সেগুলি প্রদর্শন করতে পারেন ।


1

ব্যবহারের সারি ছাড়াই, আপনি এটির proc_open()মতো ব্যবহার করতে পারেন :

    $descriptorspec = array(
        0 => array("pipe", "r"),
        1 => array("pipe", "w"),
        2 => array("pipe", "w")    //here curaengine log all the info into stderror
    );
    $command = 'ping stackoverflow.com';
    $process = proc_open($command, $descriptorspec, $pipes);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.