Sử dụng child_ process.execSync nhưng giữ đầu ra trong bảng điều khiển


160

Tôi muốn sử dụng execSync phương thức đã được thêm vào trong NodeJS 0.12 nhưng vẫn có đầu ra trong cửa sổ giao diện điều khiển từ đó tôi chạy tập lệnh Node.

Ví dụ: nếu tôi chạy tập lệnh NodeJS có dòng sau tôi muốn xem toàn bộ đầu ra của lệnh rsync "trực tiếp" bên trong bảng điều khiển:

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

Tôi hiểu rằng execSyncsẽ trả về thông số của lệnh và tôi có thể in nó ra bàn điều khiển sau khi thực thi nhưng theo cách này tôi không có đầu ra "trực tiếp" ...

Câu trả lời:


324

Bạn có thể chuyển stdio cha mẹ cho tiến trình con nếu đó là những gì bạn muốn:

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

3
Điều đó có nghĩa là tiến trình con sẽ sử dụng các luồng stdin, stdout và stderr của cha mẹ. Vì vậy, khi tiến trình con viết cho một trong số chúng, nó thực sự sẽ được ghi trực tiếp vào luồng cha mẹ.
Gregers

7
Đây là một câu trả lời rất có giá trị, vì tài liệu chính thức không thực sự rõ ràng về cú pháp dự kiến.
chikamichi

49
Thay vì [0,1,2]tôi đã sử dụng 'inherit', tương đương [process.stdin, process.stdout, process.stderr]hoặc [0,1,2]theo tài liệu
Kurt

10
Liên kết chính xác đến options.stdiotài liệu: nodejs.org/api/child_ process.html#child_ process_options_stdio
Shaun Lebron

2
@Booligoosh Thay vì chỉ cần thêm {stdio:'inherit'}, bạn phải thêm .toString () và sau đó gọi console.log bằng tay với kết quả. Ngoài ra, nó thậm chí không đáp ứng yêu cầu câu hỏi khi thấy đầu ra lệnh "trực tiếp". Tôi không nghĩ nó "đơn giản hơn nhiều", thực tế tôi không nghĩ nó đơn giản hơn chút nào.
boileau

19

Bạn chỉ có thể sử dụng .toString().

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

Điều này đã được thử nghiệm trên Node v8.5.0, tôi không chắc chắn về các phiên bản trước. Theo @etov , nó không hoạt động v6.3.1- Tôi không chắc chắn về giữa.


3
Điều này không hoạt động khi thất bại (mã trạng thái! = 0) vì .execSync()ném một Errorthể hiện.
Álvaro González

Không làm việc cho tôi, tức là đầu ra chỉ được viết sau khi lệnh kết thúc. Điều này áp dụng cho một phiên bản cụ thể? nút của tôi -v: v6.3.1
etov

Vui lòng xem xét cập nhật câu trả lời để lưu ý rằng nó chỉ áp dụng cho các phiên bản nút nhất định - điều này sẽ làm cho nó hữu ích hơn với những người khác
etov

1
Downvote kể từ bây giờ theo cách liên quan đến câu hỏi liên quan đến đầu ra trong khi lệnh được thực thi.
karfau

14

Trừ khi bạn chuyển hướng thiết bị xuất chuẩn và thiết bị xuất chuẩn như câu trả lời được chấp nhận cho thấy, điều này là không thể với execSync hoặc spawnSync. Không chuyển hướng stdout và stderr, các lệnh đó chỉ trả về stdout và stderr khi lệnh được hoàn thành.

Để làm điều này mà không chuyển hướng thiết bị xuất chuẩn và thiết bị xuất chuẩn, bạn sẽ cần sử dụng sinh sản để làm điều này nhưng nó khá đơn giản:

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);
});

Tôi đã sử dụng lệnh ls liệt kê đệ quy các tệp để bạn có thể kiểm tra nhanh. Spawn lấy đối số đầu tiên là tên thực thi mà bạn đang cố chạy và là đối số thứ hai, nó lấy một chuỗi các chuỗi đại diện cho mỗi tham số bạn muốn truyền cho tệp thực thi đó.

Tuy nhiên, nếu bạn được thiết lập bằng cách sử dụng execSync và không thể chuyển hướng thiết bị xuất chuẩn hoặc thiết bị xuất chuẩn vì một số lý do, bạn có thể mở một thiết bị đầu cuối khác như xterm và truyền cho nó một lệnh như vậy:

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

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

Điều này sẽ cho phép bạn xem lệnh của bạn đang làm gì trong thiết bị đầu cuối mới nhưng vẫn có cuộc gọi đồng bộ.


2
Ví dụ sử dụng sinh sản có thể đúng, nhưng tuyên bố mở về việc không sử dụng execSync là không chính xác. Xem câu trả lời từ @gregers
AgDude
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.