child_process 在 Nodejs 中的表现如何
How does child_process behave in Nodejs
我有一个可用的 Nodejs 代码,但是,child_process 库的行为很奇怪,我只是想知道这个库是如何工作的。
我的代码尝试从 S3 下载 SSL 证书,然后使用 child_process 库基于现有文件创建两个新文件。
const AWS = require('aws-sdk');
const fs = require('fs');
const child_process = require("child_process");
const exec = require('child_process').exec;
var s3 = new AWS.S3();
var filePath = '../Desktop/Certs/'
var bucketName = 'neb.certificates' //replace example bucket with your s3 bucket name
var params = {
Bucket: bucketName,
Prefix: 'dev/jenkins.secure.care/',
};
s3.listObjectsV2(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else {
// console.log(data.Contents)
var len = data.Contents.length
for(var i=0; i<len; i++){
var key = data.Contents[i]["Key"]
var newPath = filePath.concat(key.substring(31))
const downloadFile = (newPath, bucketName, key) => {
//construct getParam
var getParams = {
Bucket: bucketName,
Key: key
};
s3.getObject(getParams, (err, data) => {
if (err) console.error(err)
fs.writeFileSync(newPath, data.Body.toString())
// console.log(`${newPath} has been created!`)
})
}
downloadFile(newPath, bucketName, key)
}
}
});
exec('mv ../Desktop/Certs/cert.pem ../Desktop/Certs/jenkins.crt', (err, stdout, stderr) => {
if (err) {
console.error(err);
return;
}
console.log(stdout);
});
exec('mv ../Desktop/Certs/privkey.pem ../Desktop/Certs/jenkins.key', (err, stdout, stderr) => {
if (err) {
console.error(err);
return;
}
console.log(stdout);
});
所以当我第一次 运行 代码时,它只将证书从 S3 下载到本地文件夹,它没有创建其他 2 个文件。然后我必须第二次 运行 它来创建额外的文件。
然而,我只想运行它一次,它拥有我所期望的一切。
我已经添加了一个代码,它可以休眠 5 秒,然后创建额外的文件,但是它并没有解决我的问题,这意味着我仍然 运行 两次代码来获取所有内容。
child_process.execSync("sleep 5");
请帮忙
看来这里的问题是您的代码的异步执行。在此示例中,发生了什么:
- 运行
s3.listObjectsV2()
和 完成后,触发回调(但不是现在,将来)
- 运行 首先
exec()
和 完成后,触发回调(但不是现在,将来 )
- 运行 第二个
exec()
和 完成后,触发回调(但不是现在,将来 )
然后这三个步骤立即被触发,一个接一个。他们每个人都有自己的回调,在未来 触发。好的,但是 未来 是什么时候? - 确切地!你不知道。在你的情况下,exec()
中的那两个回调可能在 s3
的回调之前被触发,这就是它不起作用的原因。
此处的解决方案是确保那些 exec()
在 s3.listObjects
之后触发。所以你有两个选择:首先是从 s3
中做出承诺,就像这样:s3.listObjectsV2(params).promise()
和 await
,然后在 .then((data) => {})
中你有你的 data
并且在 .catch((error) => {})
中你有你的 error
。或者您可以简单地将这些 exec()
放入 s3
调用的回调中。
根据解决方案 2(来自评论),您的代码应如下所示:
const AWS = require('aws-sdk');
const fs = require('fs');
const child_process = require("child_process");
const exec = require('child_process').exec;
var s3 = new AWS.S3();
var filePath = '../Desktop/Certs/'
var bucketName = 'neb.certificates' //replace example bucket with your s3 bucket name
var params = {
Bucket: bucketName,
Prefix: 'dev/jenkins.secure.care/',
};
s3.listObjectsV2(params, async function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else {
// console.log(data.Contents)
var len = data.Contents.length
for(var i=0; i<len; i++){
var key = data.Contents[i]["Key"]
var newPath = filePath.concat(key.substring(31))
const downloadFile = (newPath, bucketName, key) => {
//construct getParam
var getParams = {
Bucket: bucketName,
Key: key
};
return s3.getObject(getParams).promise();
};
const downloadData = await downloadFile(newPath, bucketName, key).catch(console.error);
fs.writeFileSync(newPath, downloadData.Body.toString());
console.log(newPath, 'created');
}
//rename files
console.log('renaming first cert.pem');
exec('mv ../Desktop/Certs/cert.pem ../Desktop/Certs/jenkins.crt', (err, stdout, stderr) => {
if (err) {
console.error(err);
return;
}
console.log(stdout);
});
console.log('renaming second privkey.pem');
exec('mv ../Desktop/Certs/privkey.pem ../Desktop/Certs/jenkins.key', (err, stdout, stderr) => {
if (err) {
console.error(err);
return;
}
console.log(stdout);
});
}
});
我有一个可用的 Nodejs 代码,但是,child_process 库的行为很奇怪,我只是想知道这个库是如何工作的。
我的代码尝试从 S3 下载 SSL 证书,然后使用 child_process 库基于现有文件创建两个新文件。
const AWS = require('aws-sdk');
const fs = require('fs');
const child_process = require("child_process");
const exec = require('child_process').exec;
var s3 = new AWS.S3();
var filePath = '../Desktop/Certs/'
var bucketName = 'neb.certificates' //replace example bucket with your s3 bucket name
var params = {
Bucket: bucketName,
Prefix: 'dev/jenkins.secure.care/',
};
s3.listObjectsV2(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else {
// console.log(data.Contents)
var len = data.Contents.length
for(var i=0; i<len; i++){
var key = data.Contents[i]["Key"]
var newPath = filePath.concat(key.substring(31))
const downloadFile = (newPath, bucketName, key) => {
//construct getParam
var getParams = {
Bucket: bucketName,
Key: key
};
s3.getObject(getParams, (err, data) => {
if (err) console.error(err)
fs.writeFileSync(newPath, data.Body.toString())
// console.log(`${newPath} has been created!`)
})
}
downloadFile(newPath, bucketName, key)
}
}
});
exec('mv ../Desktop/Certs/cert.pem ../Desktop/Certs/jenkins.crt', (err, stdout, stderr) => {
if (err) {
console.error(err);
return;
}
console.log(stdout);
});
exec('mv ../Desktop/Certs/privkey.pem ../Desktop/Certs/jenkins.key', (err, stdout, stderr) => {
if (err) {
console.error(err);
return;
}
console.log(stdout);
});
所以当我第一次 运行 代码时,它只将证书从 S3 下载到本地文件夹,它没有创建其他 2 个文件。然后我必须第二次 运行 它来创建额外的文件。
然而,我只想运行它一次,它拥有我所期望的一切。
我已经添加了一个代码,它可以休眠 5 秒,然后创建额外的文件,但是它并没有解决我的问题,这意味着我仍然 运行 两次代码来获取所有内容。
child_process.execSync("sleep 5");
请帮忙
看来这里的问题是您的代码的异步执行。在此示例中,发生了什么:
- 运行
s3.listObjectsV2()
和 完成后,触发回调(但不是现在,将来) - 运行 首先
exec()
和 完成后,触发回调(但不是现在,将来 ) - 运行 第二个
exec()
和 完成后,触发回调(但不是现在,将来 )
然后这三个步骤立即被触发,一个接一个。他们每个人都有自己的回调,在未来 触发。好的,但是 未来 是什么时候? - 确切地!你不知道。在你的情况下,exec()
中的那两个回调可能在 s3
的回调之前被触发,这就是它不起作用的原因。
此处的解决方案是确保那些 exec()
在 s3.listObjects
之后触发。所以你有两个选择:首先是从 s3
中做出承诺,就像这样:s3.listObjectsV2(params).promise()
和 await
,然后在 .then((data) => {})
中你有你的 data
并且在 .catch((error) => {})
中你有你的 error
。或者您可以简单地将这些 exec()
放入 s3
调用的回调中。
根据解决方案 2(来自评论),您的代码应如下所示:
const AWS = require('aws-sdk');
const fs = require('fs');
const child_process = require("child_process");
const exec = require('child_process').exec;
var s3 = new AWS.S3();
var filePath = '../Desktop/Certs/'
var bucketName = 'neb.certificates' //replace example bucket with your s3 bucket name
var params = {
Bucket: bucketName,
Prefix: 'dev/jenkins.secure.care/',
};
s3.listObjectsV2(params, async function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else {
// console.log(data.Contents)
var len = data.Contents.length
for(var i=0; i<len; i++){
var key = data.Contents[i]["Key"]
var newPath = filePath.concat(key.substring(31))
const downloadFile = (newPath, bucketName, key) => {
//construct getParam
var getParams = {
Bucket: bucketName,
Key: key
};
return s3.getObject(getParams).promise();
};
const downloadData = await downloadFile(newPath, bucketName, key).catch(console.error);
fs.writeFileSync(newPath, downloadData.Body.toString());
console.log(newPath, 'created');
}
//rename files
console.log('renaming first cert.pem');
exec('mv ../Desktop/Certs/cert.pem ../Desktop/Certs/jenkins.crt', (err, stdout, stderr) => {
if (err) {
console.error(err);
return;
}
console.log(stdout);
});
console.log('renaming second privkey.pem');
exec('mv ../Desktop/Certs/privkey.pem ../Desktop/Certs/jenkins.key', (err, stdout, stderr) => {
if (err) {
console.error(err);
return;
}
console.log(stdout);
});
}
});