নোড.জেএস চাইল্ড প্রসেসটি স্প্যান করে এবং টার্মিনাল আউটপুট লাইভ পান


113

আমার কাছে একটি স্ক্রিপ্ট আছে যা 'হাই' আউটপুট করে, এক সেকেন্ডের জন্য ঘুমায়, 'হাই' আউটপুট দেয়, 1 সেকেন্ডের জন্য ঘুমায় এবং আরও অনেক কিছু। এখন আমি ভেবেছিলাম এই মডেলটির সাহায্যে আমি এই সমস্যা মোকাবেলা করতে সক্ষম হব।

var spawn = require('child_process').spawn,
temp    = spawn('PATH TO SCRIPT WITH THE ABOVE BEHAVIOUR');

temp.stdout.pipe(process.stdout);

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


1
শিশু প্রক্রিয়া লিখিত হয়, তাহলে pythonতখন পাস করতে ভুলবেন না -uএটা কনসোল আউটপুট বাফার না করার জন্য পতাকা, অন্যথায় এটি স্ক্রিপ্ট দেখতে কেমন হবে লাইভ নয় stackoverflow.com/a/49947671/906265
Aivaras

Npmjs.com/package/cross-spawn অন্য কিছুর পরিবর্তে ব্যবহার করুন । এটা আরও ভাল।
অ্যান্ড্রু কোস্টার

উত্তর:


92

আমি এখনও নোড.জেএস দিয়ে আমার পা ভিজে যাচ্ছি, তবে আমার কয়েকটি ধারণা আছে। প্রথমত, আমি বিশ্বাস করি এর execFileপরিবর্তে আপনার ব্যবহার করা দরকার spawn;execFileযখন আপনার কোনও স্ক্রিপ্টের পথ রয়েছে তখনই forspawn কোনও পরিচিত কমান্ড কার্যকর করার জন্য যা নোড.জে আপনার সিস্টেমের পথের বিরুদ্ধে সমাধান করতে পারে।

1. বাফার আউটপুট প্রক্রিয়া করতে একটি কলব্যাক সরবরাহ করুন :

var child = require('child_process').execFile('path/to/script', [ 
    'arg1', 'arg2', 'arg3', 
], function(err, stdout, stderr) { 
    // Node.js will invoke this callback when process terminates.
    console.log(stdout); 
});  

২. শিশু প্রক্রিয়া স্টাডাউট স্ট্রিমে ( শ্রেনীর 9 ম শ্রেনীর ) শ্রোতা যুক্ত করুন

var child = require('child_process').execFile('path/to/script', [ 
    'arg1', 'arg2', 'arg3' ]); 
// use event hooks to provide a callback to execute when data are available: 
child.stdout.on('data', function(data) {
    console.log(data.toString()); 
});

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

child = require('child_process').execFile('path/to/script', [ 
    'arg1', 'arg2', 'arg3', 
], { 
    // detachment and ignored stdin are the key here: 
    detached: true, 
    stdio: [ 'ignore', 1, 2 ]
}); 
// and unref() somehow disentangles the child's event loop from the parent's: 
child.unref(); 
child.stdout.on('data', function(data) {
    console.log(data.toString()); 
});

8
বোনাস পয়েন্টস যদি আপনি ব্যাখ্যা করতে পারেন কীভাবে এক্সিকিউটিভ () দিয়ে এটি করতে হয় যেমন আমার শেল সেন্টিমিডি চালানো দরকার।
ডায়নামিকডান

2
আপনি ব্যবহার করতে পারেন child.spawn()সঙ্গে shellকরার অপশন সেট truenodejs.org/api/…
সিডএক্স

5
আপনি চাইল্ড.স্টডআউটকে সরাসরি প্রক্রিয়াতেও স্টপআউট করতে পারেনchild.stdout.pipe(process.stdout);
ডার্কডেপটেক্ট

@ ডায়নামিকডান javascript let childProcess = exec ( './script-to-run --arg1 arg1value', ( error, stdout, stderror ) => { console.log( '[CALLBACK]: ' + error ); // or stdout or stderror } ); // Same as with spawn: childProcess.stdout.on ( 'data', ( data ) => { console.log( '[LIVE]: ' + data ); // Here's your live data! } );
রিক

130

এটি এখন অনেক সহজ (6 বছর পরে)!

স্প্যান একটি চাইল্ডঅবজেক্ট ফেরত দেয় , যা আপনি তারপরে ইভেন্টগুলির জন্য শুনতে পারবেন । ঘটনাগুলি হ'ল:

  • ক্লাস: চাইল্ডপ্রসেস
    • ইভেন্ট: 'ত্রুটি'
    • ইভেন্ট: 'প্রস্থান'
    • ইভেন্ট: 'বন্ধ'
    • ইভেন্ট: 'সংযোগ বিচ্ছিন্ন'
    • ইভেন্ট: 'বার্তা'

চাইল্ডঅবজেক্ট থেকে কিছু গুচ্ছ অবজেক্ট রয়েছে , সেগুলি হ'ল :

  • ক্লাস: চাইল্ডপ্রসেস
    • child.stdin
    • child.stdout
    • child.stderr
    • child.stdio
    • child.pid
    • child.connected
    • child.kill ([সংকেত])
    • চাইল্ড.সেন্ড (বার্তা [, সেন্ড হ্যান্ডল] [, কলব্যাক])
    • child.disconnect ()

চাইল্ডঅবজেক্ট সম্পর্কে আরও তথ্য এখানে দেখুন: https://nodejs.org/api/child_process.html

অসমনিয়ত

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

child_process.spawn (...); (নোড v0.1.90)

var spawn = require('child_process').spawn;
var child = spawn('node ./commands/server.js');

// You can also use a variable to save the output 
// for when the script closes later
var scriptOutput = "";

child.stdout.setEncoding('utf8');
child.stdout.on('data', function(data) {
    //Here is where the output goes

    console.log('stdout: ' + data);

    data=data.toString();
    scriptOutput+=data;
});

child.stderr.setEncoding('utf8');
child.stderr.on('data', function(data) {
    //Here is where the error output goes

    console.log('stderr: ' + data);

    data=data.toString();
    scriptOutput+=data;
});

child.on('close', function(code) {
    //Here you can get the exit code of the script

    console.log('closing code: ' + code);

    console.log('Full output of script: ',scriptOutput);
});

আপনি কীভাবে কলব্যাক + অ্যাসিনক্রোনাস পদ্ধতি ব্যবহার করবেন তা এখানে :

var child_process = require('child_process');

console.log("Node Version: ", process.version);

run_script("ls", ["-l", "/home"], function(output, exit_code) {
    console.log("Process Finished.");
    console.log('closing code: ' + exit_code);
    console.log('Full output of script: ',output);
});

console.log ("Continuing to do node things while the process runs at the same time...");

// This function will output the lines from the script 
// AS is runs, AND will return the full combined output
// as well as exit code when it's done (using the callback).
function run_script(command, args, callback) {
    console.log("Starting Process.");
    var child = child_process.spawn(command, args);

    var scriptOutput = "";

    child.stdout.setEncoding('utf8');
    child.stdout.on('data', function(data) {
        console.log('stdout: ' + data);

        data=data.toString();
        scriptOutput+=data;
    });

    child.stderr.setEncoding('utf8');
    child.stderr.on('data', function(data) {
        console.log('stderr: ' + data);

        data=data.toString();
        scriptOutput+=data;
    });

    child.on('close', function(code) {
        callback(scriptOutput,code);
    });
}

উপরের পদ্ধতিটি ব্যবহার করে, আপনি স্ক্রিপ্ট থেকে ক্লায়েন্টকে প্রতিটি আউটপুট প্রেরণ করতে পারেন (উদাহরণস্বরূপ Socket.io ব্যবহার করে প্রতিটি লাইন প্রেরণ করতে যখন আপনি ইভেন্টগুলি পাবেন stdoutবাstderr )।

সমলয়

আপনি যদি নোডটি যা করছেন তা বন্ধ করতে এবং স্ক্রিপ্টটি শেষ না হওয়া পর্যন্ত অপেক্ষা করতে চান , আপনি সিঙ্ক্রোনাস সংস্করণ ব্যবহার করতে পারেন:

child_process.spawnSync (...);(নোড v0.11.12 +)

এই পদ্ধতিটি নিয়ে সমস্যাগুলি:

  • যদি স্ক্রিপ্টটি সম্পূর্ণ হতে কিছু সময় নেয় তবে আপনার সার্ভারটি সেই পরিমাণ সময়ের জন্য স্তব্ধ হয়ে যাবে!
  • স্ক্রিপ্টটি শেষ হয়ে গেলেই স্ট্যান্ডআউটটি ফিরে আসবে । এটি সমকালীন হওয়ার কারণে এটি বর্তমান লাইন শেষ না হওয়া অবধি চলতে পারে না। সুতরাং স্প্যান লাইন শেষ না হওয়া পর্যন্ত এটি 'স্টডআউট' ইভেন্ট ক্যাপচারে অক্ষম।

এটি কিভাবে ব্যবহার করতে:

var child_process = require('child_process');

var child = child_process.spawnSync("ls", ["-l", "/home"], { encoding : 'utf8' });
console.log("Process finished.");
if(child.error) {
    console.log("ERROR: ",child.error);
}
console.log("stdout: ",child.stdout);
console.log("stderr: ",child.stderr);
console.log("exist code: ",child.status);

11
+1, এটি এখন সঠিক উত্তর হিসাবে চয়ন করা উচিত। কেবল একটি নোট, কলব্যাকের ডেটা ভেরিয়েবলটি বাফার অবজেক্ট হিসাবে আসে। আপনি ব্যবহার করতে পারেন child.stdout.setEncoding('utf8')যদি আপনি UTF8 স্ট্রিং আসছে চাই।
আশিস

2
stdoutপ্রক্রিয়াটি যদি অব্যাহত থাকে তবে আপনার যদি অ্যাসিক্রোনালিকভাবে তথ্যের প্রয়োজন হয় তবে এটি কাজ করে না ।
ক্রিশ্চিয়ান হুজার

2
আরে @ খ্রিস্টিয়ানহুজার! অ্যাসিঙ্ক এবং সিঙ্ক উভয়ই অন্তর্ভুক্ত করার জন্য আমি আমার উত্তর আপডেট করেছি: ডি
কেটি

যদি আপনার কাছে কোনও স্ক্রিপ্ট থাকে যা: console.log("Output 1"); console.error("Boom"); console.log("Output 2");এবং আমি করছি spawnAsync('node ./script.js')... আপনি কীভাবে আউটপুট ক্রম সংরক্ষণ করবেন? আমার আউটপুটটি সর্বদা ভুল ক্রমে বেরিয়ে আসে।
ব্রায়ান রায়

অবগতির জন্য, এটা আরও সহজ যদি আপনি ব্যবহার করেন pipeবা pipelineঅথবা আপনার কাছে যথাযথ অপশন মধ্যে পাস spawn
ধনী

25

এখানে আমি খুঁজে পেয়েছি সবচেয়ে পরিষ্কার পদ্ধতির:

require("child_process").spawn('bash', ['./script.sh'], {
  cwd: process.cwd(),
  detached: true,
  stdio: "inherit"
});

15
এটা ঠিক কি করছে? কেন এটি কাজ করে? এটি ক্লিনার পদ্ধতির কেন?
কিশমিশ্রদ্ধ

16

একটি শিশু প্রসেসে যখন এনপিএম তৈরি করি তখন "এনপিএম ইনস্টল" কমান্ড থেকে লগিং আউটপুট পেতে আমার একটু সমস্যা হয়েছিল। নির্ভরতার রিয়েলটাইম লগিং প্যারেন্ট কনসোলে প্রদর্শিত হয়নি।

আসল পোস্টার যা চায় তা করার সহজ উপায়টি এটি (উইন্ডোগুলিতে এনপিএম স্প্যান করে সমস্ত কিছু প্যারেন্ট কনসোলে লগ করুন):

var args = ['install'];

var options = {
    stdio: 'inherit' //feed all child process logging into parent process
};

var childProcess = spawn('npm.cmd', args, options);
childProcess.on('close', function(code) {
    process.stdout.write('"npm install" finished with code ' + code + '\n');
});

3

আমি নিজেকে প্রায়শই এই কার্যকারিতাটির প্রয়োজনীয়তা পেয়েছি যে এটি এটিকে std-pour নামক লাইব্রেরিতে প্যাকেজ করেছি । এটি আপনাকে একটি কমান্ড কার্যকর করতে এবং রিয়েল টাইমে আউটপুট দেখতে দেয়। সহজভাবে ইনস্টল করতে:

npm install std-pour

তারপরে একটি কমান্ড কার্যকর করতে এবং রিয়েলটাইমের আউটপুটটি দেখতে এটি যথেষ্ট সহজ:

const { pour } = require('std-pour');
pour('ping', ['8.8.8.8', '-c', '4']).then(code => console.log(`Error Code: ${code}`));

এটি প্রতিশ্রুতি ভিত্তিক যাতে আপনি একাধিক কমান্ড চেইন করতে পারেন। এটি এমনকি ফাংশনের স্বাক্ষরের সাথে সামঞ্জস্যপূর্ণ child_process.spawnযাতে এটি আপনি যে কোনও জায়গায় ব্যবহার করছেন প্রতিস্থাপনের ড্রপ হওয়া উচিত।


1
@ কোডি গ্রান্থাম খুশী এটি আপনার জন্য কাজ করছে! আপনি সমস্ত মনে হয় আপনি কিছু দুর্দান্ত কাজ করছেন তাই আমি আশা করি এটি আপনাকে চালিয়ে রাখবে।
জোয়েল বি


1

পিএইচপি-এর মতো পাস্ত্রু

import { spawn } from 'child_process';

export default async function passthru(exe, args, options) {
    return new Promise((resolve, reject) => {
        const env = Object.create(process.env);
        const child = spawn(exe, args, {
            ...options,
            env: {
                ...env,
                ...options.env,
            },
        });
        child.stdout.setEncoding('utf8');
        child.stderr.setEncoding('utf8');
        child.stdout.on('data', data => console.log(data));
        child.stderr.on('data', data => console.log(data));
        child.on('error', error => reject(error));
        child.on('close', exitCode => {
            console.log('Exit code:', exitCode);
            resolve(exitCode);
        });
    });
}

ব্যবহার

const exitCode = await passthru('ls', ['-al'], { cwd: '/var/www/html' })

0

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

মূলত, আমার কাছে একটি এনপিএম স্ক্রিপ্ট রয়েছে যা গুলপকে কল করে, পরবর্তী সময়ে যে কোনও টাস্কটি ব্যবহার করে তাকে ডাকে child_process.exec ওএসের উপর নির্ভর করে ব্যাশ বা ব্যাচের স্ক্রিপ্ট চালানোর জন্য করে। হয় স্ক্রিপ্ট গুল্পের মাধ্যমে বিল্ড প্রক্রিয়া চালায় এবং তারপরে কিছু বাইনারিগুলিতে কল করে যা গুলপ আউটপুট নিয়ে কাজ করে।

এটি অন্যের মতো (স্প্যান ইত্যাদি), তবে সম্পূর্ণ হওয়ার জন্য এটি কীভাবে করা যায় তা এখানে:

// INCLUDES
import * as childProcess from 'child_process'; // ES6 Syntax


// GLOBALS
let exec = childProcess.exec; // Or use 'var' for more proper 
                              // semantics, though 'let' is 
                              // true-to-scope


// Assign exec to a variable, or chain stdout at the end of the call
// to exec - the choice, yours (i.e. exec( ... ).stdout.on( ... ); )
let childProcess = exec
(
    './binary command -- --argument argumentValue',
    ( error, stdout, stderr ) =>
    {
        if( error )
        {
            // This won't show up until the process completes:
            console.log( '[ERROR]: "' + error.name + '" - ' + error.message );
            console.log( '[STACK]: ' + error.stack );

            console.log( stdout );
            console.log( stderr );
            callback();            // Gulp stuff
            return;
        }

        // Neither will this:
        console.log( stdout );
        console.log( stderr );
        callback();                // Gulp stuff
    }
);

এখন এটি ইভেন্ট শ্রোতা যুক্ত করার মতোই সহজ। এর জন্য stdout:

childProcess.stdout.on
(
    'data',
    ( data ) =>
    {
        // This will render 'live':
        console.log( '[STDOUT]: ' + data );
    }
);

এবং এর জন্য stderr:

childProcess.stderr.on
(
    'data',
    ( data ) =>
    {
        // This will render 'live' too:
        console.log( '[STDERR]: ' + data );
    }
);

মোটেও খারাপ নয় - এইচটিএইচ

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.