узел.js выполняет системную команду синхронно
мне нужно узел.js функции
result = execSync('node -v');
что будет одновременно выполните данную командную строку и верните все stdout'Ed по этому тексту команды.
ps. Синхронизация-это неправильно. Я знаю. Только для личного пользования.
обновление
теперь у нас есть решение mgutz, которое дает нам код выхода, но не stdout! Все еще ждем более точного ответ.
обновление
mgutz обновил свой ответ и решение здесь :)
Также, как dgo.а упоминается, есть автономный модуль exec-sync
обновление 2014-07-30
ShellJS Либ прибыли. Считайте, что это лучший выбор на данный момент.
обновление 2015-02-10
НАКОНЕЦ-ТО! NodeJS 0.12 поддерживает execSync
нативно.
Смотрите официальный docs
12 ответов:
узел.js (начиная с версии 0.12 - так на некоторое время) поддерживает
execSync
:child_process.execSync(command[, options])
теперь вы можете напрямую сделать это:
const execSync = require('child_process').execSync; code = execSync('node -v');
и он сделает то, что вы ожидаете. (По умолчанию для передачи результатов ввода-вывода в родительский процесс). Обратите внимание, что вы также можете
spawnSync
сейчас.
посмотреть execSync библиотека.
Это довольно легко сделать с узел-ffi. Я бы не рекомендовал для серверных процессов,но для общих утилит разработки это делается. Установите библиотеку.
npm install node-ffi
пример:
var FFI = require("node-ffi"); var libc = new FFI.Library(null, { "system": ["int32", ["string"]] }); var run = libc.system; run("echo $USER");
[EDIT Jun 2012: Как получить STDOUT]
var lib = ffi.Library(null, { // FILE* popen(char* cmd, char* mode); popen: ['pointer', ['string', 'string']], // void pclose(FILE* fp); pclose: ['void', [ 'pointer']], // char* fgets(char* buff, int buff, in) fgets: ['string', ['string', 'int','pointer']] }); function execSync(cmd) { var buffer = new Buffer(1024), result = "", fp = lib.popen(cmd, 'r'); if (!fp) throw new Error('execSync error: '+cmd); while(lib.fgets(buffer, 1024, fp)) { result += buffer.readCString(); }; lib.pclose(fp); return result; } console.log(execSync('echo $HOME'));
использовать ShellJS модуль.
exec без предоставления обратного вызова.
пример:
var version = exec('node -v').output;
есть отличный модуль для управления потоком в узле.Яш называется asyncblock. Если перенос кода в функцию подходит для вашего случая, можно рассмотреть следующий пример:
var asyncblock = require('asyncblock'); var exec = require('child_process').exec; asyncblock(function (flow) { exec('node -v', flow.add()); result = flow.wait(); console.log(result); // There'll be trailing \n in the output // Some other jobs console.log('More results like if it were sync...'); });
Это невозможно в узел.js, оба
child_process.spawn
иchild_process.exec
были построены с нуля, чтобы быть асинхронным.Подробнее см.:https://github.com/ry/node/blob/master/lib/child_process.js
Если вы действительно хотите иметь эту блокировку, то поместите все, что должно произойти после этого в обратный вызов, или создайте свою собственную очередь, чтобы справиться с этим блокирующим способом, я полагаю, вы могли бы использовать асинхронность.js для этой задачи.
или, в если у вас есть слишком много времени, чтобы тратить, взломать вокруг в узле.js IT self.
Это самый простой способ я нашел:
exec-Sync: https://github.com/jeremyfa/node-exec-sync
(не путать с execSync.)
Выполните команду оболочки синхронно. Используйте это для сценариев миграции, программ cli, но не для обычного кода сервера.пример:
var execSync = require('exec-sync'); var user = execSync('echo $USER'); console.log(user);
просто добавить, что, хотя есть несколько usecases, где вы должны использовать их,
spawnSync
/execFileSync
/execSync
были добавлены в узел.js в этих коммитах:https://github.com/joyent/node/compare/d58c206862dc...e8df2676748e
вы можете достичь этого с помощью волокон. Например, используя мой Общая библиотека узлов, код будет выглядеть так:
result = require('subprocess').command('node -v');
Я привык реализовывать
"synchronous"
вещи в конце функции обратного вызова. Не очень приятно, но это работает. Если вам нужно реализовать последовательность выполнения командной строки, вам нужно обернутьexec
в некоторую именованную функцию и рекурсивно вызвать ее. Этот шаблон, кажется, можно использовать для меня:SeqOfExec(someParam); function SeqOfExec(somepParam) { // some stuff // ..... // ..... var execStr = "yourExecString"; child_proc.exec(execStr, function (error, stdout, stderr) { if (error != null) { if (stdout) { throw Error("Smth goes wrong" + error); } else { // consider that empty stdout causes // creation of error object } } // some stuff // ..... // ..... // you also need some flag which will signal that you // need to end loop if (someFlag ) { // your synch stuff after all execs // here // ..... } else { SeqOfExec(someAnotherParam); } }); };
У меня была аналогичная проблема, и я закончил писать расширение узла для этого. Вы можете проверить репозиторий Git. Это с открытым исходным кодом и бесплатно и все, что хороший материал !
https://github.com/aponxi/npm-execxi
ExecXI представляет собой узел расширения, написанные на C++, чтобы выполнить команды shell один за другим, выводя выходные данные команды на консоль в в реальном времени. Необязательно прикованный, и раскованных способов присутствуют; смысл что вы можете выбрать чтобы остановить скрипт, после того, как команда не (последовательно), или вы можете продолжать, как будто ничего не произошло !
инструкции по использованию находятся в ReadMe file. Не стесняйтесь делать запросы на вытягивание или отправлять вопросы!
EDIT:
однако он еще не возвращает stdout... Просто выводит их в режиме реального времени.он делает сейчас. Ну, я только что выпустил его сегодня. Может быть, мы сможем построить на этом.во всяком случае, я думал об этом стоило упомянуть.
вы можете выполнять синхронные операции оболочки в nodejs следующим образом:
var execSync = function(cmd) { var exec = require('child_process').exec; var fs = require('fs'); //for linux use ; instead of && //execute your command followed by a simple echo //to file to indicate process is finished exec(cmd + " > c:\stdout.txt && echo done > c:\sync.txt"); while (true) { //consider a timeout option to prevent infinite loop //NOTE: this will max out your cpu too! try { var status = fs.readFileSync('c:\sync.txt', 'utf8'); if (status.trim() == "done") { var res = fs.readFileSync("c:\stdout.txt", 'utf8'); fs.unlinkSync("c:\stdout.txt"); //cleanup temp files fs.unlinkSync("c:\sync.txt"); return res; } } catch(e) { } //readFileSync will fail until file exists } }; //won't return anything, but will take 10 seconds to run console.log(execSync("sleep 10")); //assuming there are a lot of files and subdirectories, //this too may take a while, use your own applicable file path console.log(execSync("dir /s c:\usr\docs\"));
EDIT-этот пример предназначен для сред windows, при необходимости отрегулируйте его для собственных нужд linux
на самом деле у меня была ситуация, когда мне нужно было запускать несколько команд одну за другой из пакета.сценарий предварительной установки json таким образом, чтобы он работал как на Windows, так и на Linux/OSX, поэтому я не мог полагаться на неядерный модуль.
Так вот что я придумал:
#cmds.coffee childproc = require 'child_process' exports.exec = (cmds) -> next = -> if cmds.length > 0 cmd = cmds.shift() console.log "Running command: #{cmd}" childproc.exec cmd, (err, stdout, stderr) -> if err? then console.log err if stdout? then console.log stdout if stderr? then console.log stderr next() else console.log "Done executing commands." console.log "Running the follows commands:" console.log cmds next()
Вы можете использовать его как это:
require('./cmds').exec ['grunt coffee', 'nodeunit test/tls-config.js']
EDIT: как уже отмечалось, это фактически не возвращает вывод или не позволяет использовать результат команд в Узловой программе. Один идея для этого-использовать обратные вызовы LiveScript. http://livescript.net/