Nút không hỗ trợ tất cả syscall posix.
Xem chủ đề này
A way to call execl, execle, execlp, execv, execvP or execvp from Node.js
Vụ tai nạn được dự kiến như bạn đang sử dụng một cái gì đó mà không có sẵn cho bạn. Như đã thảo luận trong các chủ đề trên, bạn cần phải thể tạo exec của riêng bạn
index.cc
#include <nan.h>
#include <fcntl.h>
#include <unistd.h>
int doNotCloseStreamsOnExit(int desc) {
int flags = fcntl(desc, F_GETFD, 0);
if (flags < 0) return flags;
flags &= ~FD_CLOEXEC; //clear FD_CLOEXEC bit
return fcntl(desc, F_SETFD, flags);
}
void copyArray(char* dest[], unsigned int offset, v8::Local<v8::Array> src) {
unsigned int length = src->Length();
for (unsigned int i = 0; i < length; i++) {
v8::String::Utf8Value arrayElem(Nan::Get(src, i).ToLocalChecked()->ToString());
std::string arrayElemStr (*arrayElem);
char* tmp = new char[arrayElemStr.length() +1];
strcpy(tmp, arrayElemStr.c_str());
dest[i + offset] = tmp;
}
}
void setEnv(v8::Local<v8::Array> src) {
unsigned int length = src->Length();
v8::Local<v8::String> keyProp = Nan::New<v8::String>("key").ToLocalChecked();
v8::Local<v8::String> valueProp = Nan::New<v8::String>("value").ToLocalChecked();
for (unsigned int i = 0; i < length; i++) {
v8::Local<v8::Object> obj = Nan::Get(src, i).ToLocalChecked()->ToObject();
v8::String::Utf8Value objKey(Nan::Get(obj, keyProp).ToLocalChecked()->ToString());
v8::String::Utf8Value objValue(Nan::Get(obj, valueProp).ToLocalChecked()->ToString());
std::string objKeyStr (*objKey);
char *key = const_cast<char*> (objKeyStr.c_str());
std::string objValueStr (*objValue);
char *value = const_cast<char*> (objValueStr.c_str());
setenv(key, value, 1);
}
}
void Method(const Nan::FunctionCallbackInfo<v8::Value>& info) {
if (info.Length() < 3) {
return;
}
if (!info[0]->IsString()) {
return;
}
// get command
v8::String::Utf8Value val(info[0]->ToString());
std::string str (*val);
char *command = const_cast<char*> (str.c_str());
// set env on the current process
v8::Local<v8::Array> envArr = v8::Local<v8::Array>::Cast(info[1]);
setEnv(envArr);
// build args: command, ...args, NULL
v8::Local<v8::Array> argsArr = v8::Local<v8::Array>::Cast(info[2]);
char* args[argsArr->Length() + 2];
args[0] = command;
copyArray(args, 1, argsArr);
args[argsArr->Length() + 1] = NULL;
// fix stream flags
doNotCloseStreamsOnExit(0); //stdin
doNotCloseStreamsOnExit(1); //stdout
doNotCloseStreamsOnExit(2); //stderr
execvp(command, args);
}
void Init(v8::Local<v8::Object> exports) {
exports->Set(Nan::New("exec").ToLocalChecked(),
Nan::New<v8::FunctionTemplate>(Method)->GetFunction());
}
NODE_MODULE(exec, Init)
index.js
'use strict';
var addon = require('bindings')('addon');
var path = require('path');
var fs = require('fs');
module.exports = function(cmd, env, args) {
if (!cmd) {
throw new Error('Command is required');
}
var envArr = Object.keys(env || {}).map(key => {
return {
key,
value: env[key],
};
});
addon.exec(cmd, envArr, args || []);
};
PS: Mã đăng từ https://github.com/OrKoN/native-exec, trong trường hợp liên kết không hoạt động trong tương lai
Ngoài ra một điều khác bạn không nên cố gắng thực hiện một cái gì đó mà cần để có được TTY, bạn sẽ thêm rất nhiều phức tạp trong trường hợp đó. Vì vậy, chạy python sẽ cần phải kiểm soát TTY của bạn.
Vâng tôi biết, execl đó thay thế biểu diễn bộ nhớ quá trình. Ban đầu tôi sử dụng nó để sinh ra quá trình con với 'fork()' syscall –
Node không hỗ trợ tất cả các syscall posix. Xem chủ đề này https://stackoverflow.com/questions/34290403/a-way-to-call-execl-execle-execlp-execv-execvp-or-execvp-from-node-js. Sự cố xảy ra khi bạn đang sử dụng thứ gì đó không có sẵn cho bạn –