2021年9月20日 星期一

Windows 上 Python 多版本管理(Python Launcher for Windows)

Python 3.x 語法常與 Python 2.x 不相容,
所以Python的windows安裝檔,從3.3開始多了Python launcher可安裝,
Python launcher 可方便選擇使用哪個版本的Python來執行。

安裝時有勾選安裝「py launcher」即會安裝Python launcher,
安裝後可於命列列操作。



[操作]
查看 Python launcher 指令說明
>py -h
Python Launcher for Windows Version 3.9.6150.1013

usage:
py [launcher-args] [python-args] [script [script-args]]
.....

列出安裝的所有Python版本,有「*」星號的是預設的版本
>py -0
Installed Pythons found by py Launcher for Windows
 -3.9-64 *
 -3.9-32
 -2.7-64

列出各版本Python安裝的路徑
>py -0p
Installed Pythons found by py Launcher for Windows
 -3.9-64        C:\Program Files\Python39\python.exe *
 -3.9-32        C:\Users\user\AppData\Local\Programs\Python\Python39-32\python.exe
 -2.7-64        C:\Users\user\.windows-build-tools\python27\python.exe

執行預設版本
>py
Python 3.9.6 (tags/v3.9.6:db3ff76, Jun 28 2021, 15:26:21) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 

執行指定版本
>py -2
Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 

執行指定版本,且為32-bit的版本
>py -3-32
Python 3.9.7 (tags/v3.9.7:1016ef3, Aug 30 2021, 20:05:41) [MSC v.1929 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 

使用 2.7 版執行script
>py -2.7 test.py

為不同版本的 Python 安裝套件(package)
>py -3.9 -m pip install 套件名稱

版本查看
>py --version
Python 3.9.6

>py -V
Python 3.9.6

>py -3 -V
Python 3.9.6

>py -3.9 -V
Python 3.9.6



參考:


Python 出現 ImportError: No module named PIL 錯誤

Python 出現 ImportError: No module named PIL 錯誤
原因:程式中有使用 Pillow 影像處理套件(from PIL import Image),但系統沒有安裝 Pillow 套件
解決:安裝 Pillow 套件
> pip install Pillow


參考:


其他:安裝 pip 套件管理工具
下載 https://bootstrap.pypa.io/get-pip.py
>py get-pip.py


Linux sudo 設定 log,紀錄 sudo 執行的指令

 Linux sudo 設定 log,紀錄 sudo 執行的指令

[建立放log的資料夾]

# mkdir /var/log/sudo
# chmod 700 /var/log/sudo
建立初始log檔
# touch /var/log/sudo/sudo.log
# chmod 600 /var/log/sudo/sudo.log
沒先建立初始log檔 sudo.log 也是可以,有帳號使用 sudo 時,就會自動產生 sudo.log,
但是 sudo.log 的群組會是該使用者的群組。



[編輯 /etc/sudoers,新增log檔設定]
# visudo
新增
Defaults log_host, log_year, logfile=/var/log/sudo/sudo.log
其中
log_host:紀錄host
log_year:紀錄年份


沒有 log_host, log_year 的情況 (xyz2 執行 sudo -u xyz less /home/xyz/.bash_history)
Sep 17 05:57:26 : xyz2 : TTY=pts/2 ; PWD=/home/xyz2 ; USER=xyz ;
    COMMAND=/bin/less /home/xyz/.bash_history
有 log_host, log_year 的情況 (xyz2 執行 sudo -u xyz less /home/xyz/.bash_history)
Sep 17 06:00:53 2021 : xyz2 : HOST=localhost : TTY=pts/2 ; PWD=/home/xyz2
    ; USER=xyz ; COMMAND=/bin/less /home/xyz/.bash_history



[log檔設定 logrotate]
# vi /etc/logrotate.d/sudo
/var/log/sudo/*.log {
    daily
    dateext
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    #建立新log檔
    create 0600 root root
}

強制執行一次 logrotate,測試是否正常
logrotate -vf /etc/logrotate.d/sudo




參考:

2021年8月22日 星期日

JavaScript 去除小數字串後面多餘的零

例如,"1.00200" => "1.002"

可以將小數字串轉型成數字,後面的零會自動去除。 
如果不想轉成數字,可以用正規表達式處理:

  1. \.0*$」:符合 ".0"、".00"、".000"....這類的字串尾,找出來,去除。
  2. (\.\d*[1-9])0+$」:符合".10"、".010"、".0100"、".100100000"....這類的字串尾,找出來,去除後面連續的"0",並將前面小數點「.」到最後一個不是「0」的部分,保留暫存為第一個變數「$1」。
  3. 用OR將兩者綜合起來:
    • 小數字串.replace(/\.0*$|(\.\d*[1-9])0+$/, '$1')
    • 第一個條件「\.0*$」,沒用「()」小括號紀錄符合的部分,所以沒有$1的值,效果猶如直接去除符合的部分。
      (如果這個條件也用了小括號儲存變數,連後面第二個條件的小括號,整個比對樣式共有兩個小括號,會變成第一個括號為$1,第二個括號為$2)
    • 第二個條件「(\.\d*[1-9])0+$」用「()」小括號將符合的字串範圍中,要保留的部分存成$1變數,整個符合範圍用$1取代。
/**
 * 去除小數字串後面多餘的零
 * @param {String} num_str
 * @returns {String}
 */
var removeFloatTrailingZero = function (num_str) {
   //new String("test"),typeof 是 object,所以多一個 instanceof 判斷
    if (typeof num_str === "string" || num_str instanceof String) {
        //字串
    } else {
       //避免隨意傳入非字串變數,導致後面replace()出錯
        num_str = String(num_str);//null、undefined 不能用 toString()
    }
    return num_str.replace(/\.0*$|(\.\d*[1-9])0+$/, '$1');
};

Regular Expression 取代效果:
https://regex101.com/r/l4FOO8/1/

測試字串:
0
0.0
0.00
1.0
10.00
100
200.010
200.01023000
200.100
200.1002
去除符合樣式,保留$1的最終結果:
0
0
0
1
10
100
200.01
200.01023
200.1
200.1002


其他:
若改成用「#$1」取代
數字字串.replace(/\.0*$|(\.\d*[1-9])0+$/, '#$1'),
可較清晰的觀察比對樣式條件OR、變數$1的取代邏輯。
https://regex101.com/r/Ng06RE/1
0
0#
0#
1#
10#
100
200#.01
200#.01023
200#.1
200.1002



2021年7月6日 星期二

php-fpm.conf 中的 request_terminate_timeout 設定

 request_terminate_timeout:

  • 預設值0,代表off
  • 可設定單位:s(秒、預設)、m(分)、h(小時)、d(日)
  • 效果:執行逾時,會發生錯誤中斷執行
  • 錯誤訊息:
    PHP error log => execution timed out, terminating
    Nginx => 502 Bad Gateway
  • 使用時機:當 max_execution_time 執行超時限制無作用時,又有需求須中止執行時,可考慮設定此參數。

官網說明:
request_terminate_timeout mixed
The timeout for serving a single request after which the worker process will be killed.
This option should be used when the 'max_execution_time' ini option does not stop script execution for some reason.
A value of '0' means 'Off'. Available units: s(econds)(default), m(inutes), h(ours), or d(ays). Default value: 0.


max_execution_time 說明:
max_execution_time 只算 PHP Script 本身執行的時間。
system calls using system(), stream operations, database queries...這些不列入計算。
例如,使用 sleep()延遲執行花的時間、curl_init()抓取網站花的時間,都不屬於PHP本身Script執行時間,都不會導致超過 max_execution_time 限制產生逾時。
若這些時間也要加入執行逾時考量,可以考慮使用 request_terminate_timeout 參數。





參考: