2018年7月10日 星期二

PHP SimpleXMLElement 輸出的 XML 增加 CDATA

使用 SimpleXMLElement 產生 XML 時,若遇到內容有特殊字元,
SimpleXMLElement 不會自動轉換特殊字元, 也不會自動加上 CDATA
所以內容有特殊字元時,若沒先處理再傳給 SimpleXMLElement,便會出錯。

若想使用加上 CDATA 的方式,可如以下幫 SimpleXMLElement 加上 addCData 功能。
class SimpleXMLExtended extends \SimpleXMLElement {
    /**
     * 將節點的值加上 CDATA
     * @param string $cdata_text 節點的值
     */
    public function addCData($cdata_text) {
        $node = dom_import_simplexml($this);
        $no = $node->ownerDocument;
        $node->appendChild($no->createCDATASection($cdata_text));
    }
}
使用
$sxe = new \SimpleXMLExtended('<xyz></xyz>');
$sxe->addChild('aa')->addCData('test');
$xml = $sxe->asXML();
//輸出結果
//<?xml version="1.0"?>
//<xyz><aa><![CDATA[test]]></aa></xyz>


參考:
php - How to write CDATA using SimpleXmlElement? - Stack Overflow

PHP 去除 XML 開頭的宣告標籤

例如使用 SimpleXMLElement 產生的的 XML 字串,第一行開頭固定會有 的XML宣告標籤。 若想去除,可用 DOMDocument 輸出:
$xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><xyz>AAA</xyz>';//原XML字串
$t_xml = new \DOMDocument();
$t_xml->loadXML($xml);
//新的XML字串
$xml_out = $t_xml->saveXML($t_xml->documentElement);//<xyz>AAA</xyz>


參考:
PHP DomDocument output without <?xml version="1.0" encoding="UTF-8"?> - Stack Overflow

CentOS 查看由 systemd 所管理服務的日誌記錄

由 systemd 管理的服務,產生的日誌 log 記錄,是由 systemd-journald 服務處理。

[設定檔]
位置
/etc/systemd/journald.conf

設定說明可查看
man journald.conf

「Storage」 是控制日誌儲存的位置,有以下設定值。
volatile:儲存在記憶體中。在 /run/log/journal/ 目錄下,所以重開機便會不見。
persistent:儲存在硬碟。在 /var/log/journal 目錄下,目錄若不存在,會自動建立。
auto:若 /var/log/journal 目錄存在,則如同 persistent 儲存在硬碟。否則如同 volatile 儲存在記憶體。
none:不保存日誌。但不影響日誌轉發。
「SystemMaxUse=, SystemKeepFree=, SystemMaxFileSize=, RuntimeMaxUse=, RuntimeKeepFree=,RuntimeMaxFileSize=」
是檔案日誌大小限制,已有適當預設值,也會自動滾動輪替,無特殊需求應該不用修改。

修改設定檔案後,須重啟 systemd-journald 服務。
例如原本日誌原本預設儲存在記憶體。修改為將日誌儲存在硬碟、限制日誌檔案大小為100M。
$ vi /etc/systemd/journald.conf

Storage=persistent
SystemMaxUse=100M
$ systemctl restart systemd-journald
重啟後,可發現系統自動建立了 /var/log/journal 目錄,


[日誌指令]
查看日誌
$ journalctl

查看 kernel 訊息
$ journalctl -k

查看啟動編號(0:目前的編號,每次重開機會多一個,若日誌儲存在記憶體,重開機會清空,則只會有編號0這一個)
$ journalctl --list-boots
-3 87786fd3c7274fa49d88644a6f84eaec 三 2018-07-10 15:29:51 CST—三 2018-07-10 16:21:51 CST
-2 d69bfb38d2b342479175dc6b161caaa3 三 2018-07-10 16:21:56 CST—三 2018-07-10 16:23:41 CST
-1 5eeccbecaacb49d4aa70a04b119f6e7e 三 2018-07-10 16:23:47 CST—三 2018-07-10 16:25:21 CST
 0 b22ae5b9e5834647a09b654ceab32479 三 2018-07-10 16:25:26 CST—三 2018-07-10 16:26:31 CST

查看啟動後的日誌
$ journalctl -b 啟動編號

指定某時間開始的日誌
$ journalctl --since="2018-01-05 15:10:20"
$ journalctl --since "20 min ago"
$ journalctl --since 'yesterday'

查看指定時段內的日誌
$ journalctl --since="2018-01-05 15:10:20" --until="2018-01-05 18:30:00"

顯示最新日誌
$ journalctl -f

查看指定系統服務的日誌
$ journalctl -u 系統服務名稱

日誌先後順數反向顯示(新的日誌顯示在前面)
$ journalctl -r

特定PID的日誌
$ journalctl _PID=指定PID數字

顯示幾筆最新的日誌
$ journalctl -n 數字

過濾日誌級別
$ journalctl -p 級別數字或英文
0:emerg
1:alert
2:crit
3:err
4:warning
5:notice
6:info
7:debug

日誌使用的空間
$ journalctl --disk-usage



參考:
systemd (正體中文) - ArchWiki
RHEL / CentOS 7 管理記錄檔 — Journald – Linux 技術手札
如何使用Journalctl查看和操作Systemd日志
Suse Doc: 管理指南 - journalctl:查询 systemd 日记 - September 08 2013
journald.conf 中文手册 [金步国]


Node js 將 log 輸出到檔案

開發時會使用 console.log 將變數內容、訊息輸出到畫面查看, 若想輸出到檔案,則可自訂個 log2file 函式。
var fs = require('fs');
var util = require('util');
var log_file = fs.createWriteStream(__dirname + '/debug.log', {flags: 'w'});
var log2file = function (v) {
    log_file.write(util.format(v) + '\n');
};

用法
let aa={a:123, b:456};
log2file(aa);


參考:
node.js - Node: log in a file instead of the console - Stack Overflow


2018年3月24日 星期六

Node.js 讀取儲存在 Redis 的 PHP Sesion 資料

[Node.js 安裝 php-unserialize 模組]
php-unserialize 可以反序列化 PHP serialize() 後的資料=>使用 unserialize(string)
也可以解析 PHP 儲存的 seesion 資料(例如儲存在 Redis 的Sessoin) =>使用 unserializeSession(string)
$ npm install php-unserialize --save

[Node.js 讀取儲存在 Redis 的 PHP Session 範例]
"use strict";

//redis 連線設定
const REDIS_HOST = "127.0.0.1";
const REDIS_PORT = 6379;
const REDIS_OPTS = {};
const REDIS_PASS = "密碼";

let redis = require('redis');
let redis_client = redis.createClient(REDIS_PORT, REDIS_HOST, REDIS_OPTS);
redis_client.on("error", function (err) {
    console.log("Error:" + err);
});
redis_client.auth(REDIS_PASS);//密碼驗證


var PHPUnserialize = require('php-unserialize');
let php_sess_key = "PHP Session儲存在Redis的Key";//例如PHPREDIS_SESSION:n47g4vh1qt2pltplkd3lhifes2
//讀取資料後,利用 callback function 處理取得資料
redis_client.get(php_sess_key, function (err, results) {
    if (null !== err) {
        try {
            //使用 unserializeSession 解析 session 資料
            let sess = PHPUnserialize.unserializeSession(results);
            console.log(sess);
            console.log(sess.user.u_id);
        } catch (err) {
            //錯誤處理.....
        }
    }
});


參考:
GitHub - naholyr/js-php-unserialize: JavaScript tool to unserialize data taken from PHP. It can parse "serialize()" output, or even serialized sessions data.