我做了一個node_exec.js的檔案
內容是一系列的指令程式碼,如下..
// http://nodejs.org/api.html#_child_processes
var sys = require('sys');
var exec = require('child_process').exec;
var child;
child = exec("gitbook init H223456789/", function (error, stdout, stderr) {
sys.print('stdout: ' + stdout);
sys.print('stderr: ' + stderr);
sys.print('\n\n');
if (error !== null) {
console.log('exec error: ' + error);
}
});
child = exec("gitbook build H223456789/ H223456789/book", function (error, stdout, stderr) {
sys.print('stdout: ' + stdout);
sys.print('stderr: ' + stderr);
sys.print('\n\n');
if (error !== null) {
console.log('exec error: ' + error);
}
});
child = exec("gitbook pdf H223456789/ H223456789/book/book.pdf", function (error, stdout, stderr) {
sys.print('stdout: ' + stdout);
sys.print('stderr: ' + stderr);
sys.print('\n\n');
if (error !== null) {
console.log('exec error: ' + error);
}
});
我的OS是Ubuntu圖形化版
剛開始接觸NODE
了解到~正常情況都要在終端機執行node指令才能執行上述程式碼
(node node_exec.js)
但我想製作給客戶端可以操作
也就是..我想做一個網頁(例如index.html)
當中有一顆按鈕~點擊後會執行node_exec.js
請問該如何做到?
另外...
上述程式碼中有個很明顯是身分證字號的字串(H223456789)
分布在每一個child=exec...的函式中
那個字串我打算換成一個變數..例如var aID;
再打算把剛剛提到的網頁按鈕送個值給node_exec.js
請問這部分又該如何傳遞?
兩個問題~
麻煩IT邦的朋友協助解答~
或是給個參考資料~
謝謝~
我不確定你的意思是不是指要讓node成為常駐服務。
如果是這樣的話,你用
npm install forever
安裝forever
用法跟node差不多,不明白可以查一下forever的指令集。
用forever執行的node.js檔案就會在背景常駐執行(連當掉都會幫你重新執行)
不是常駐服務
而是有觸發動作才執行
這麼說吧~
我問題中的程式碼(node_exec.js)
是一串原本要有使用者自己輸入指令
並透過這些指令產生電子書檔案(PDF)
這邊的使用者就是我自己
但..我想將它發展成一個網頁
讓客戶端的使用者也可以使用
可是..總不能讓他們直接連到伺服器輸入指令阿~
而且..不是所有使用者都懂指令
所以我寫好上述的程式碼
那串程式碼我自己試過是可以動作的
只不過..還是處於由我自己輸入指令才能執行(node node_exec.js)
我想讓這串指令(node node_exec.js)
變成可以讓其他使用者很直覺式的按鈕
當點擊按鈕後便會自動執行一系列指令
當然..我的想法是..網頁畫面上會有個給使用者輸入自己的身分證
當點擊按鈕後~將身分證值傳送給node_exec.js使用
我覺得你想得太簡單XD,為了安全,其實不應該讓使用者輸入指令讓他可以在伺服器端執行。
你需要先分析需求,把動作包裝成函數或物件,然後客戶或是你自己可以只挑選選項然後執行,程式會根據選項以及一些必要的參數,組合你包裝好的函數或物件方法來執行,產出結果。
fillano老大~
我沒有要讓使用者輸入指令
基本上..他們畫面上看得到的..
只有一個text input和submit送出鈕(送出身分證號用)
指令的部分..則是會在使用者送出資訊後在後端運作(即node_exec.js)
那就沒問題XD
快的話,套用express,然後做一個靜態的html,透過ajax呼叫用express做出來的api。你的exec就在api中執行。
三次呼叫exec的非同步執行,如果有步驟上的相依性,那可以用Promise串起來。
嗯!就費公說的express了吧!
花一個上午去大略研究了一下express
然後去網上搜尋相關資訊
然後複製貼上修修改改寫了以下的程式
index.html...
<script src="jquery-3.2.1.min.js"></script>
<script type="text/javascript">
$(function(){
$('#sendnode').click(function(e){
e.preventDefault();
console.log('sendnode clicked');
var data = document.getElementById("aID").value;
$.ajax({
type: 'POST',
data: JSON.stringify(data),
contentType: 'application/json',
url: 'http://172.17.0.1:3000/endpoint', //172.17.0.1是我本機設定的IP
success: function(data) {
alert('success');
}
});
});
});
</script>
<input type="text" id="aID" name="aID">
<input type="button" id="sendnode" name="sendnode" value="sendnode">
node_exec.js...
var express = require('express');
var app = express();
//app.use(express.bodyParser());
app.post('/endpoint', function(req, res){
/*var obj = {};
console.log('body: ' + JSON.stringify(req.body));
res.send(req.body);*/
var sys = require('sys');
var exec = require('child_process').exec;
var child;
var aID="H227654321";
child = exec("gitbook init "+aID+"/", function (error, stdout, stderr) {
sys.print('stdout: ' + stdout);
sys.print('stderr: ' + stderr);
sys.print('\n\n');
if (error !== null) {
console.log('exec error: ' + error);
}
});
child = exec("gitbook build "+aID+"/ "+aID+"/book", function (error, stdout, stderr) {
sys.print('stdout: ' + stdout);
sys.print('stderr: ' + stderr);
sys.print('\n\n');
if (error !== null) {
console.log('exec error: ' + error);
}
});
child = exec("gitbook pdf "+aID+"/ "+aID+"/book/book.pdf", function (error, stdout, stderr) {
sys.print('stdout: ' + stdout);
sys.print('stderr: ' + stderr);
sys.print('\n\n');
if (error !== null) {
console.log('exec error: ' + error);
}
});
});
app.listen(3000);
目前aID設固定..
實際上得要取得我index.html傳出的值(還不知道怎麼抓..==)
執行過後..沒有動作..
不只指令連跑都沒跑
從一開始的ajax就沒有成功開啟url了
更不用說傳值..
肯定有毛病..還在研究..==
當然阿~~單獨在終端機執行node node_exec.js倒是挺成功的..= =
你要不要說一下為什麼不能用你熟悉的 php 去執行 node node_exec.js
? 找不到 node 指令? 權限問題?
先說說我伺服器的環境
我的OS是Ubuntu
當中安裝了docker
並在docker建立image(鏡像)
image包裝的就是apache+php
當然..想要能夠操作node指令或是gitbook指令
只要進入docker裡的image..同樣用裡面的終端機安裝node和gitbook
到這邊都挺OK的~
但莫名其妙的是...
只要我一跳出docker(exit)
node就不見了...(不過gitbook卻還在)
(但gitbook需要node才能運作)
所以..我到現在為止的提問是..
跳開跑PHP走後台這一步
而是直接在Ubuntu操作
因為我在Ubuntu操作任何指令都沒有問題
只是..這些操作行為都是在本機端的終端機上手動執行..
而我現在的工作就是把這些操作變成網頁
讓其他使用者點擊就能完成這些指令
跑指令的方法很多
node只是我想到的其中一個方法
PHP也是..只是試過後失敗
下方froce大大提的python也是其中的方法之一
如果node在失敗..我會試用python
如果如果...
都沒其他方法了...
我會考慮跟公司說另架一台server
一台獨立..但不跑docker的apache server
在這種情況下..應該就不會出現node安裝後不見的問題了
所以你的問題應該是 docker 為什麼沒有保存你安裝的 node js
不知道你是怎麼用的, 我先貼我平常的作法
這樣啟動你的image: docker run --name test_node -d your/image_name tail -f /dev/null
然後這樣進入 docker 終端機: docker exec -it test_node env TERM=xterm bash
把你要安裝的東西裝好, exit 之後停止 docker: docker stop test_node
再啟動他: docker start test_node
最後進去看看東西還在不在: docker exec -it test_node env TERM=xterm bash
試試看?
如果上面的步驟 ok, 那就弄成 Dockerfile 可以省事一些
可以詢問一下 這是甚麼意思嗎? env TERM=xterm
因為我的步驟都跟你一樣...
就是少了 env TERM=xterm
我現在電腦在做別的事 暫時無法測試
所以先問問 env TERM=xterm 是甚麼意思
晚點再來上機試試~
只是補上環境變數, 讓一些全畫面的指令能正常一點
一樣..command not found....= =
PATH 對嗎? 如果打完整路徑能找到 node ?
你 nodejs 是用 nvm 安裝的嗎? 我看到這篇: https://stackoverflow.com/questions/36367498/docker-nodejs-not-found
weiclin 可以回覆了..= =
https://www.evernote.com/shard/s626/sh/5c977335-5dee-4ca7-8a43-2ace7983f3f5/2e01679969749d0a1d8abb8bee9a6cb3
上面網址是我自己筆記安裝gitbook的步驟
其中有一行nvm install 6.10.0
就是安裝node用的(現在是8.0.0)
當全部安裝完後
我都會下指令node -v
以及gitbook --version
除了查看版本號
同時也是為了確認指令是否存在
當我exit docker後再進入docker..
同樣下指令node -v
以及gitbook --version
會顯示bash: node: command not found
以及bash: gitbook: command not found
的訊息..
然後我再次執行nvm install 8.0.0
安裝node
再次下指令node -v
以及gitbook --version
後
分別各自顯示node與gitbook的版本號
由上述測試證明..
只有node會不見
至於PATH問題..
當我安裝好node或gitbook後
不管我在哪個路徑下執行指令
都可以顯示版本號..
所以..應該跟PATH無關..吧..= =
試了你給的安裝方法
node不會消失了0.0
以你的版本, 如果每次進入 docker 都執行一次 source ~/.profile
會好嗎?
這招我有試過~
一樣~哈哈~
倒是我用你上面給的網站
把安裝方法改成這樣~↓↓↓curl -sL https://deb.nodesource.com/setup_4.x | bash -
apt-get install -y nodejs
離開docker再進去就沒有消失了
(PS..現在版本為8.0.0..所以4.x改成8.x)
接下來就是想辦法讓php exec可以執行gitbook指令了..
(原本以為之前沒辦法執行是因為node不見..經一個上午測試..才知道..gitbook本來就不能動作..= = 研究中...搞不好日後會再開一個相關問題..= =)
嗯, 那問題就是出在 nvm 沒有正確運作, 在 docker 裡也不太需要 nvm 就是了
我想你要的應該是透過現有的node跑起來的server,去fork一個child process執行系統指令,系統指令就是"node node_exec.js"
底下示範fork child process執行node --version
var exec = require('child_process').exec;
var cmd = 'node --version';
exec(cmd, function(error, stdout, stderr) {
// command output is in stdout
console.log(stdout, stderr);
});
Update:因為新手不能回應所以我回在下面:
你誤會我意思了.
你要給使用者點擊網頁,你是不是要先架設一台server來收browser request. 這台server你可以直接用node.js + express 架設一個RESTful http daemon server, 然後在on_post handler裡面掛上我之前的範例Code.
並不需要每次收到request都要在終端機手動打node.
以你的docker架構, 你就要在php+apache那一個container也裝node, 讓php http server收到post http request時, 去invoke 安裝在同一個docker container上的node執行檔 (此時node process的parent process是你的http server, 而不是你的login shell)
我沒在用node,不過我在python會這樣做,提供你參考。
在node裡應該也有可以執行shell script的函數/物件。
好像是 child_process下的exec。
用ajax好像太牛刀小用了。
事實上...
您的作法我了解~也有做過~
只是當時的後台是apache+php
php裡面也有可以跑exec的函式
基本指令例如cd.ls....等等都可以正常運作
但我要執行的指令是gitbook
gitbook本身又得要靠node運作
還有很多種種因素
造成我gitbook這個指令都無法運作
(主要還是因為我架設的環境問題)
所以我才找尋別的方法來執行指令
先說,我沒很仔細看討論串喔,只是我有一樣的需求,然後找一個python的解法試了一下可行這樣。
import os
nodeFileToOpen='trynode.js'
result = os.popen('node '+nodeFileToOpen)
print (result.read()) #if there's a result return
input() #prevent closing window
運作是沒問題的,不過我現在的問題是,
trynode.js這個檔案中的console.log並不會顯示在這個python的執行視窗...
我還不知道怎麼處理它。