8

Выполнение бинарного файла командной строки с помощью Node.js

10

Я занимаюсь переносом библиотеки командной строки с Ruby на Node.js. В своем коде я выполняю несколько сторонних бинарных файлов при необходимости. Не уверен, каким образом лучше всего это реализовать в Node.js.

Вот пример на Ruby, где я вызываю PrinceXML для конвертации файла в PDF:

cmd = system("prince -v builds/pdf/book.html -o builds/pdf/book.pdf")

Какой эквивалентный код будет на Node.js?

4 ответ(ов)

0

Теперь вы можете использовать shelljs (начиная с node v4) следующим образом:

var shell = require('shelljs');

shell.echo('hello world');
shell.exec('node --version');

Установите shelljs с помощью команды:

npm install shelljs

Подробности можно найти на странице проекта: https://github.com/shelljs/shelljs.

0

Перевожу ваш вопрос на русский с учетом стиля ответов на StackOverflow:


Я только что написал вспомогательный класс для командной строки (CLI), который упрощает работу с Unix и Windows.

Вот пример реализации на JavaScript:

define(["require", "exports"], function (require, exports) {
    // Вспомогательный класс для удобного использования CLI в окружениях Windows и Unix.
    // Требуется библиотека underscore или lodash в глобальной области как "_".
    var Cli = (function () {
        function Cli() {}

        // Выполняет команду CLI, пробуя сначала в Windows, затем в Unix, если в первом случае не удалось.
        Cli.execute = function (command, args, callback, callbackErrorWindows, callbackErrorUnix) {
            if (typeof args === "undefined") {
                args = [];
            }
            Cli.windows(command, args, callback, function () {
                callbackErrorWindows();
                try {
                    Cli.unix(command, args, callback, callbackErrorUnix);
                } catch (e) {
                    console.log('------------- Не удалось выполнить команду: "' + command + '" в обоих окружениях. -------------');
                }
            });
        };

        // Выполняет команду в окружении Windows.
        Cli.windows = function (command, args, callback, callbackError) {
            if (typeof args === "undefined") {
                args = [];
            }
            try {
                Cli._execute(process.env.comspec, _.union(['/c', command], args));
                callback(command, args, 'Windows');
            } catch (e) {
                callbackError(command, args, 'Windows');
            }
        };

        // Выполняет команду в окружении Unix.
        Cli.unix = function (command, args, callback, callbackError) {
            if (typeof args === "undefined") {
                args = [];
            }
            try {
                Cli._execute(command, args);
                callback(command, args, 'Unix');
            } catch (e) {
                callbackError(command, args, 'Unix');
            }
        };

        // Выполняет команду, независимо от окружения.
        Cli._execute = function (command, args) {
            var spawn = require('child_process').spawn;
            var childProcess = spawn(command, args);
            childProcess.stdout.on("data", function (data) {
                console.log(data.toString());
            });
            childProcess.stderr.on("data", function (data) {
                console.error(data.toString());
            });
        };
        return Cli;
    })();
    exports.Cli = Cli;
});

А вот исходный код на TypeScript:

export class Cli {
    public static execute(command: string, args: string[] = [], callback ?: any, callbackErrorWindows ?: any, callbackErrorUnix ?: any) {
        Cli.windows(command, args, callback, function () {
            callbackErrorWindows();
            try {
                Cli.unix(command, args, callback, callbackErrorUnix);
            } catch (e) {
                console.log('------------- Не удалось выполнить команду: "' + command + '" в обоих окружениях. -------------');
            }
        });
    }

    public static windows(command: string, args: string[] = [], callback ?: any, callbackError ?: any) {
        try {
            Cli._execute(process.env.comspec, _.union(['/c', command], args));
            callback(command, args, 'Windows');
        } catch (e) {
            callbackError(command, args, 'Windows');
        }
    }

    public static unix(command: string, args: string[] = [], callback ?: any, callbackError ?: any) {
        try {
            Cli._execute(command, args);
            callback(command, args, 'Unix');
        } catch (e) {
            callbackError(command, args, 'Unix');
        }
    }

    private static _execute(command, args) {
        var spawn = require('child_process').spawn;
        var childProcess = spawn(command, args);
        childProcess.stdout.on("data", function (data) {
            console.log(data.toString());
        });
        childProcess.stderr.on("data", function (data) {
            console.error(data.toString());
        });
    }
}

Пример использования:

Cli.execute(Grunt._command, args, function (command, args, env) {
    console.log('Grunt успешно выполнен автоматически. (' + env + ')');
}, function (command, args, env) {
    console.error('------------- Выполнение команды Windows "' + command + '" не удалось, пробуем в Unix... ---------------');
}, function (command, args, env) {
    console.error('------------- Выполнение команды Unix "' + command + '" также не удалось. ---------------');
});

Если у вас есть вопросы по коду или по его использованию, не стесняйтесь спрашивать!

0

Ответ @hexacyanide почти полный. На Windows команда prince может быть представлена как prince.exe, prince.cmd, prince.bat или просто prince. Я не знаю, как упаковываются гемы, но npm-бинары идут с sh-скриптом и батч-скриптом - это npm и npm.cmd.

Если вы хотите написать переносимый скрипт, который будет работать как в Unix, так и в Windows, вам необходимо запустить правильный исполняемый файл.

Вот простая, но переносимая функция для запуска команд:

function spawn(cmd, args, opt) {
    var isWindows = /win/.test(process.platform);

    if (isWindows) {
        if (!args) args = [];
        args.unshift(cmd);
        args.unshift('/c');
        cmd = process.env.comspec;
    }

    return child_process.spawn(cmd, args, opt);
}

var cmd = spawn("prince", ["-v", "builds/pdf/book.html", "-o", "builds/pdf/book.pdf"])

// Используйте эти свойства для получения результатов выполнения:
// cmd.stdin;
// cmd.stdout;
// cmd.stderr;

Эта функция проверяет, запущен ли скрипт в Windows, и в зависимости от этого корректирует команду и аргументы для её выполнения.

0

Чтобы выполнить команду системы, такую как ls, в Node.js версии 16, вы можете использовать встроенный модуль child_process. Вот пример кода, который демонстрирует, как это сделать:

const { execSync } = require('child_process');

try {
    const output = execSync('ls'); // ваша системная команда
    console.log(output.toString()); // вывод результата на консоль
} catch (error) {
    console.error(`Ошибка выполнения команды: ${error.message}`);
}

В этом коде мы используем функцию execSync, которая выполняет команду синхронно. Результат выполнения команды будет сохранён в переменной output. Мы также оборачиваем вызов в try...catch, чтобы обработать любые ошибки, которые могут возникнуть во время выполнения команды. Не забудьте, что выполнение системных команд может быть опасным, особенно если команды формируются на основе пользовательского ввода.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь