iT邦幫忙

0

如何不透過指令執行NODE以及傳值給NODE

我做了一個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邦的朋友協助解答~
或是給個參考資料~
謝謝~

看更多先前的討論...收起先前的討論...
weiclin iT邦高手 5 級 ‧ 2017-06-06 14:40:25 檢舉
跟 php 一樣, 會有一個 node js 當服務一直開著, 再用 ajax 丟請求過去, 類似:
http://ithelp.ithome.com.tw/articles/10087627
這個方法我大概了解
只是...這些程式碼
都還是要透過node這個指令才能驅動這些js檔

如果不透過node指令執行
而是直接執行這些js檔
就會出現require is not defind這樣的錯誤訊息
weiclin iT邦高手 5 級 ‧ 2017-06-06 16:41:05 檢舉
如果你是想讓 .js 檔能當成執行檔, 加上執行權限跟 shebang 應該就可以
http://dailyjs.com/post/unix-node-arguments

但是你依然無法不安裝 node 就執行
安裝node是一定要的
我理解~~
但如何讓使用者只透過按鈕執行我寫好的node_exec.js呢?
或是有什麼方法可以反其道而行~繞個路完成也無彷~
weiclin iT邦高手 5 級 ‧ 2017-06-06 17:00:54 檢舉
方法不只一種, 底下文章參考看看
https://www.puritys.me/docs-blog/article-142
weiclin iT邦高手 5 級 ‧ 2017-06-06 17:01:32 檢舉
但基本上不會脫離 http 的架構與運作方式
2
Samと可樂快跑
iT邦研究生 3 級 ‧ 2017-06-06 15:01:16

我不確定你的意思是不是指要讓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使用

fillano iT邦超人 1 級 ‧ 2017-06-06 16:24:34 檢舉

我覺得你想得太簡單XD,為了安全,其實不應該讓使用者輸入指令讓他可以在伺服器端執行。

你需要先分析需求,把動作包裝成函數或物件,然後客戶或是你自己可以只挑選選項然後執行,程式會根據選項以及一些必要的參數,組合你包裝好的函數或物件方法來執行,產出結果。

fillano老大~
我沒有要讓使用者輸入指令
基本上..他們畫面上看得到的..
只有一個text input和submit送出鈕(送出身分證號用)

指令的部分..則是會在使用者送出資訊後在後端運作(即node_exec.js)

fillano iT邦超人 1 級 ‧ 2017-06-06 17:17:04 檢舉

那就沒問題XD

fillano iT邦超人 1 級 ‧ 2017-06-06 17:26:06 檢舉

快的話,套用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倒是挺成功的..= =

weiclin iT邦高手 5 級 ‧ 2017-06-07 12:57:31 檢舉

你要不要說一下為什麼不能用你熟悉的 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安裝後不見的問題了

weiclin iT邦高手 5 級 ‧ 2017-06-07 14:46:45 檢舉

所以你的問題應該是 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 是甚麼意思
晚點再來上機試試~

weiclin iT邦高手 5 級 ‧ 2017-06-07 15:26:48 檢舉

只是補上環境變數, 讓一些全畫面的指令能正常一點

一樣..command not found....= =

weiclin iT邦高手 5 級 ‧ 2017-06-07 16:00:06 檢舉

PATH 對嗎? 如果打完整路徑能找到 node ?

weiclin iT邦高手 5 級 ‧ 2017-06-07 16:11:59 檢舉

你 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

weiclin iT邦高手 5 級 ‧ 2017-06-08 11:30:56 檢舉

以你的版本, 如果每次進入 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本來就不能動作..= = 研究中...搞不好日後會再開一個相關問題..= =)

weiclin iT邦高手 5 級 ‧ 2017-06-08 11:58:53 檢舉

嗯, 那問題就是出在 nvm 沒有正確運作, 在 docker 裡也不太需要 nvm 就是了

0
duy
iT邦新手 5 級 ‧ 2017-06-07 09:53:33

我想你要的應該是透過現有的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)

建議後面才來回答的大大
可以先去看看其他回覆或留言
當中會有我另外對問題做解釋的回覆

針對您的回覆
require('child_process').exec
是node才有的函式
也就是說..若您的程式碼檔名為test.js
我還是得在終端機輸入指令node test.js

我目的是如何省略操作終端機的步驟
透過html的一個按鈕去執行我已經包好的node程式(node_exec.js)

針對問題的詳情可以往上看看其他回覆唷~^..^

0
froce
iT邦研究生 4 級 ‧ 2017-06-07 11:33:13

我沒在用node,不過我在python會這樣做,提供你參考。

  1. http送出參數,進到後台(建議用POST,然後做好前後台驗證)。
  2. 後台的控制碼內,把參數接進來,然後用os.execute("python 程式 參數"),也就是利用後台執行os的shell script。
  3. 把原本的程式改寫成可讀系統參數的程式。

在node裡應該也有可以執行shell script的函數/物件。
好像是 child_process下的exec。
用ajax好像太牛刀小用了。

看更多先前的回應...收起先前的回應...

事實上...
您的作法我了解~也有做過~
只是當時的後台是apache+php
php裡面也有可以跑exec的函式
基本指令例如cd.ls....等等都可以正常運作
但我要執行的指令是gitbook
gitbook本身又得要靠node運作
還有很多種種因素
造成我gitbook這個指令都無法運作
(主要還是因為我架設的環境問題)
所以我才找尋別的方法來執行指令

所以...我會想問...
您回覆的第一點提到的後台是甚麼?
PHP?ASP?JS?PYTHON?

froce iT邦研究生 4 級 ‧ 2017-06-07 12:01:41 檢舉

python。
你可以寫個小程式先去執行看看gitbook,看看會不會比用PHP好。

import os

os.execute("gitbook指令")
fillano iT邦超人 1 級 ‧ 2017-06-07 13:42:05 檢舉

如果是無法執行,是不是先確認一下有沒有權限問題?

我要發表回答

立即登入回答