ใช้ child_process.execSync แต่เก็บเอาท์พุทไว้ในคอนโซล


160

ฉันต้องการใช้execSyncวิธีการที่ถูกเพิ่มใน NodeJS 0.12 แต่ยังคงมีผลลัพธ์ในหน้าต่างคอนโซลที่ฉันใช้สคริปต์ Node

เช่นถ้าฉันเรียกใช้สคริปต์ NodeJS ซึ่งมีบรรทัดต่อไปนี้ฉันต้องการดูผลลัพธ์เต็มรูปแบบของคำสั่ง rsync "live" ในคอนโซล:

require('child_process').execSync('rsync -avAXz --info=progress2 "/src" "/dest"');

ฉันเข้าใจว่าexecSyncส่งคืน ouput ของคำสั่งและฉันสามารถพิมพ์ไปยังคอนโซลหลังการดำเนินการ แต่ด้วยวิธีนี้ฉันไม่มีเอาต์พุต "สด" ...

คำตอบ:


324

คุณสามารถส่งstdio ของผู้ปกครองไปยังกระบวนการลูกได้หากนั่นคือสิ่งที่คุณต้องการ:

require('child_process').execSync(
    'rsync -avAXz --info=progress2 "/src" "/dest"',
    {stdio: 'inherit'}
);

3
หมายความว่ากระบวนการลูกจะใช้สตรีม stdin, stdout และ stderr ของผู้ปกครอง ดังนั้นเมื่อกระบวนการลูกเขียนไปยังหนึ่งในนั้นกระบวนการนั้นจะถูกเขียนโดยตรงไปยังสตรีมของผู้ปกครอง
gregers

7
นี่เป็นคำตอบที่มีค่ามากเนื่องจากเอกสารทางการไม่ชัดเจนเกี่ยวกับไวยากรณ์ที่คาดหวัง
chikamichi

49
แทนที่จะใช้[0,1,2]ฉัน'inherit'ซึ่งเทียบเท่ากับ[process.stdin, process.stdout, process.stderr]หรือ[0,1,2]ตามเอกสาร
Kurt

10
แก้ไขลิงก์ไปยังoptions.stdioเอกสาร: nodejs.org/api/child_process.html#child_process_options_stdio
Shaun Lebron

2
@Booligoosh แทนที่จะเพิ่มเพียง{stdio:'inherit'}คุณต้องเพิ่ม. toString () แล้วโทร console.log ด้วยตนเองด้วยผล นอกจากนี้มันไม่ได้ตอบสนองความต้องการของคำถามในการดูเอาต์พุตคำสั่ง "สด" ฉันไม่คิดว่ามันจะง่ายกว่านี้จริงๆแล้วฉันไม่คิดว่ามันจะง่ายกว่านี้อีกแล้ว
boileau

19

.toString()คุณก็สามารถใช้

var result = require('child_process').execSync('rsync -avAXz --info=progress2 "/src" "/dest"').toString();
console.log(result);

สิ่งนี้ได้รับการทดสอบบนโหนดv8.5.0ฉันไม่แน่ใจเกี่ยวกับเวอร์ชันก่อนหน้า ตาม@etovมันไม่ทำงานv6.3.1- ฉันไม่แน่ใจเกี่ยวกับในระหว่าง


3
สิ่งนี้ไม่สามารถใช้งานได้กับความล้มเหลว (รหัสสถานะ! = 0) เนื่องจาก.execSync()มีการแสดงErrorตัวอย่าง
ÁlvaroGonzález

ใช้งานไม่ได้สำหรับฉันนั่นคือเอาต์พุตจะถูกเขียนหลังจากคำสั่งเสร็จสิ้นเท่านั้น สิ่งนี้ใช้ได้กับรุ่นที่ระบุหรือไม่ โหนดของฉัน -v: v6.3.1
etov

โปรดลองอัปเดตคำตอบเพื่อให้ทราบว่าใช้ได้เฉพาะกับโหนดบางรุ่นเท่านั้น - ซึ่งจะทำให้มีประโยชน์ต่อผู้อื่นมากขึ้น
etov

1
ลงคะแนนตั้งแต่ ti ในทางที่เกี่ยวข้องกับคำถามเกี่ยวกับผลลัพธ์ในระหว่างการดำเนินการคำสั่งนี้
karfau

14

นอกจากว่าคุณเปลี่ยนเส้นทาง stdout และ stderr เป็นคำตอบที่ยอมรับก็ไม่สามารถทำได้ด้วย execSync หรือ spawnSync หากไม่มีการเปลี่ยนทิศทาง stdout และ stderr คำสั่งเหล่านั้นจะส่งคืน stdout และ stderr เมื่อคำสั่งเสร็จสิ้น

ในการทำเช่นนี้โดยไม่เปลี่ยนเส้นทาง stdout และ stderr คุณจะต้องใช้การวางไข่เพื่อทำสิ่งนี้ แต่มันค่อนข้างตรงไปตรงมา:

var spawn = require('child_process').spawn;

//kick off process of listing files
var child = spawn('ls', ['-l', '/']);

//spit stdout to screen
child.stdout.on('data', function (data) {   process.stdout.write(data.toString());  });

//spit stderr to screen
child.stderr.on('data', function (data) {   process.stdout.write(data.toString());  });

child.on('close', function (code) { 
    console.log("Finished with code " + code);
});

ฉันใช้คำสั่ง ls ที่แสดงรายการไฟล์ซ้ำเพื่อให้คุณสามารถทดสอบได้อย่างรวดเร็ว วางไข่เป็นอาร์กิวเมนต์แรกชื่อปฏิบัติการที่คุณพยายามเรียกใช้และเป็นอาร์กิวเมนต์ที่สองจะใช้อาร์เรย์ของสตริงที่เป็นตัวแทนของแต่ละพารามิเตอร์ที่คุณต้องการส่งไปยังปฏิบัติการที่

อย่างไรก็ตามหากคุณตั้งค่าโดยใช้ execSync และไม่สามารถเปลี่ยนเส้นทาง stdout หรือ stderr ด้วยเหตุผลบางอย่างคุณสามารถเปิดเทอร์มินัลอื่นเช่น xterm และส่งคำสั่งให้เช่น:

var execSync = require('child_process').execSync;

execSync("xterm -title RecursiveFileListing -e ls -latkR /");

สิ่งนี้จะช่วยให้คุณเห็นว่าคำสั่งของคุณกำลังทำอะไรในเทอร์มินัลใหม่ แต่ยังมีการโทรแบบซิงโครนัส


2
ตัวอย่างที่ใช้วางไข่อาจถูกต้อง แต่คำสั่งเปิดเกี่ยวกับการไม่ใช้ execSync นั้นไม่ถูกต้อง ดูคำตอบจาก @gregers
AgDude
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.