Я все еще пытаюсь понять тонкости того, как я могу запустить команду оболочки Linux или Windows и записать вывод в node.js; в конце концов, я хочу сделать что-то подобное ...
//pseudocode
output = run_command(cmd, args)
Важная часть - это то, что output
должно быть доступно для переменной (или объекта) с глобальной областью видимости. Я попробовал следующую функцию, но по какой-то причине меня undefined
выводят на консоль ...
function run_cmd(cmd, args, cb) {
var spawn = require('child_process').spawn
var child = spawn(cmd, args);
var me = this;
child.stdout.on('data', function(me, data) {
cb(me, data);
});
}
foo = new run_cmd('dir', ['/B'], function (me, data){me.stdout=data;});
console.log(foo.stdout); // yields "undefined" <------
Мне сложно понять, где приведенный выше код ломается ... работает очень простой прототип этой модели ...
function try_this(cmd, cb) {
var me = this;
cb(me, cmd)
}
bar = new try_this('guacamole', function (me, cmd){me.output=cmd;})
console.log(bar.output); // yields "guacamole" <----
Может кто-нибудь помочь мне понять, почему try_this()
работает, а run_cmd()
не нет? FWIW, мне нужно использовать child_process.spawn
, потому что у child_process.exec
него ограничение буфера 200 КБ .
Окончательное разрешение
Я принимаю ответ Джеймса Уайта, но это точный код, который сработал для меня ...
function cmd_exec(cmd, args, cb_stdout, cb_end) {
var spawn = require('child_process').spawn,
child = spawn(cmd, args),
me = this;
me.exit = 0; // Send a cb to set 1 when cmd exits
me.stdout = "";
child.stdout.on('data', function (data) { cb_stdout(me, data) });
child.stdout.on('end', function () { cb_end(me) });
}
foo = new cmd_exec('netstat', ['-rn'],
function (me, data) {me.stdout += data.toString();},
function (me) {me.exit = 1;}
);
function log_console() {
console.log(foo.stdout);
}
setTimeout(
// wait 0.25 seconds and print the output
log_console,
250);
источник
me.stdout = "";
вcmd_exec()
предотвратить конкатенацииundefined
к началу результата.Ответы:
Здесь есть три проблемы, которые необходимо исправить:
Во-первых , вы ожидаете синхронного поведения при асинхронном использовании stdout. Все вызовы в вашей
run_cmd
функции являются асинхронными, поэтому он порождает дочерний процесс и немедленно возвращается, независимо от того, были ли некоторые, все или никакие данные считаны из стандартного вывода. Таким образом, когда вы бежитевы получаете все, что в данный момент хранится в foo.stdout, и нет никакой гарантии, что это будет, потому что ваш дочерний процесс может все еще работать.
Во-вторых , stdout является читаемым потоком , поэтому 1) событие данных может вызываться несколько раз, и 2) обратному вызову предоставляется буфер, а не строка. Легко исправить; просто измени
в
чтобы мы преобразовали наш буфер в строку и добавили эту строку к нашей переменной stdout.
В-третьих , вы можете узнать, что получили весь вывод, только когда получите событие 'end', что означает, что нам нужен другой слушатель и обратный вызов:
Итак, ваш окончательный результат таков:
источник
this.stdout = "";
внутриrun()
функции, иначе вашconsole.log(foo.sdtout);
будет иметь префиксundefined
.Упрощенная версия принятого ответа (третий пункт) просто сработала для меня.
Использование:
источник
child.stdout.on('close', (errCode) => { console.log(errCode) } )
Я использовал это более кратко:
работает отлично. :)
источник
sys.puts()
устарела в 2011 году (с Node.js v0.2.3).console.log()
Вместо этого вы должны использовать .Самый простой способ - просто использовать ShellJS lib ...
Пример EXEC:
ShellJs.org поддерживает множество распространенных команд оболочки, отображаемых как функции NodeJS, включая:
источник
shell.exec("foo.sh arg1 arg2 ... ")
. Вашfoo.sh
скрипт может ссылаться на них , используя$1
,$2
... и т.д.У меня была аналогичная проблема, и в итоге я написал для нее расширение узла. Вы можете проверить репозиторий git. Это открытый исходный код, бесплатный и все такое хорошее!
https://github.com/aponxi/npm-execxi
Инструкции по использованию находятся в файле ReadMe . Не стесняйтесь делать запросы на вытягивание или отправлять вопросы!
Я подумал, что стоит упомянуть об этом.
источник
@ TonyO'Hagan - исчерпывающий
shelljs
ответ, но я хотел бы выделить синхронную версию его ответа:источник
Синхронный однострочный:
require('child_process').execSync("echo 'hi'", function puts(error, stdout, stderr) { console.log(stdout) });
источник
В вашей
run_cmd
функции есть конфликт переменных :Просто измените его на это:
Чтобы увидеть ошибки, всегда добавляйте это:
ИЗМЕНИТЬ Ваш код не работает, потому что вы пытаетесь запустить,
dir
что не предоставляется как отдельная автономная программа. Это команда вcmd
процессе. Если вы хотите поиграть с файловой системой, используйте nativerequire( 'fs' )
.В качестве альтернативы (что я не рекомендую) вы можете создать командный файл, который затем можно будет запустить. Обратите внимание, что ОС по умолчанию запускает командные файлы через
cmd
.источник
C:\Windows\System32\netstat.exe
, это все равно не дает результатов ... Мой точный синтаксис былfoo = new run_cmd('netstat.exe', ['-an'], function (me, data){me.stdout=data;});
... Я также пробовал полный путь, пока безуспешноФактически вы ничего не возвращаете из своей функции run_cmd.
Работает нормально. :)
источник
return
это требуется, если вы правильно устанавливаете атрибуты объектаОбещанный вариант ответа, получившего наибольшее количество наград:
Использовать:
источник