PVE 疑難雜症…

  • PVE 2.0
  • 叢集設定
  • 叢集的服務基於:cman(corosync)
  • 叢集的檔案系統:pmxcfs
  • 每台叢集的設定檔:/etc/cluster/cluster.conf
  • PVE qemu/kvm 管理工具:qm

管理與確認指令:

$ pvecm status
$ pvecm nodes or cman_tool nodes

$ corosync-quorumtool -l
$ corosync-quorumtool -s

$ cat /var/log/syslog
$ cat /var/log/cluster/corosync.log

$ service cman restart
$ service pve-cluster restart
$ service node-manager restart

問題:

  • Corosync 因為 Quorum 開不起來,訊息是  Unable to load new config in corosync,代表 該台主機的 /etc/cluster/cluster.conf 內容可能出問題了,可以比較一下節點間該檔案的差異,如果不一樣可以手動同步。
  • 叢集運作是基於 multicast ,因此需要在同一個 layer 2 network,而且 switch 要支援與設定啟用群播功能(預設可能已經開了)。

node.js child_process send function

最近在用 node.js 寫一些系統管理層面的程式,有些複雜的工作需要 fork process 來做,主要的 process 用來跑 Web 跟處理主要流程,所以不打算做太多額外的工作。

var child = require('child_process').fork('./child.js');

在這裡實作的過程中想到一些設計,第一個部份是我的 child 應該設計成一個適合 require 的子模組,由他自己提供輔助函式,也由該模組 fork 自己。

var child = require('./child.js');
child.start();
child.stop();
var process;
exports.start = function() {
  var cp = require('child_process');
  process = cp.fork('./child.js');
  child.send('message', {cmd: 'start'});
}
exports.stop = function() {
  if(process)
    process.kill();
}
process.on('message', function(msg) {
  if(msg.cmd == 'start') {
     // child process start
     // do something
  }
});

由於 fork 出去的 child process 是一個子模組,所以對 parent 來說還是有一些事情想要呼叫 child 來做。依照習慣要寫一些匿名函式當參數,意思就是這個函式希望是在 child process 去跑,而不是單純用來當回呼函式使用,結果實際到這邊發現有些事情跟想像的不太一樣,process.send 當參數如果傳函式到 child process 竟然會接不到~。

仔細想想好像也不完全無道理,由於要 IPC,而 json 對函式的轉換好像本來就不太支援。

範例繼續延續上面的,這範例 msg 將收不到傳過去的函式。

..
child.helper(function(res) {
  // ...
});
..
var process;
exports.start = function() {
  var cp = require(''child_process);
  process = cp.fork('./child.js');
  child.send('message', {cmd: 'start'})
}
exports.stop = function() {
  if(process)
    process.kill();
}
exports.helper = function(handler) {
  process.send({cmd: 'helper', handler: handler});
});
process.on('message', function(msg) {
  if(msg.cmd == 'start') {
     // child process start
     // do something
  }
  else if(msg.cmd == 'helper'){
     console.log(msg);
     // { msg: 'helper' }
  }
});

這裡就讓我想到曾經看過一篇文章…撰寫乾淨的 eval 程式碼的技巧,因此就依樣畫葫蘆…就能動了!

只是要注意透過這種方式傳過去的函式所能存取到的變數已經不是表面上看到的了。而是透過 eval 執行時的 child process 的 context 了。

exports.helper = function(handler) {
  process.send({cmd: 'helper', handler: handler.toString()});
});
process.on('message', function(msg) {
  if(msg.handler) {
    eval('var handler = ' + msg.handler);
  }
  if(msg.cmd == 'start') {
     // child process start
     // do something
  }
  else if(msg.cmd == 'helper' && handler){
     handler([1, 2, 3]);
  }
});