2021年1月27日 星期三

mdadm軟RAID的刪除方法和注意事項

刪除整個RAID:


mdadm / dev / md0–fail / dev / sdb–remove / dev / sdb
mdadm / dev / md0–fail / dev / sdc–remove / dev / sdc
mdadm / dev / md0–fail / dev / sdc–remove / dev / sdd
mdadm / dev / md0–失敗/ dev / sde–刪除/ dev / sde
mdadm / dev / md0–失敗/ dev / sdf–刪除/ dev / sdf


mdadm–stop / dev / md0
mdadm–remove / dev / md0


mdadm–misc–zero-superblock / dev / sdb
mdadm–misc–zero-superblock / dev / sdc
mdadm–misc–zero-superblock / dev / sdd
mdadm–misc–zero-superblock / dev / sde
mdadm–misc–zero-超級塊/ dev / sdf


即:先刪除RAID中的所有設備,然後停止該RAID即可

為了防止系統啟動時候啟動raid
rm-f/etc/mdadm.conf
rm-f/etc/raidtab

檢查系統啟動文件中是否還有其他mdad啟動方式

vi/etc/rc.sysinit+/raid\c 

資料來源: http://www.4u.idv.tw/2018/09/14/mdadm%E8%BD%AFraid%E7%9A%84%E5%88%A0%E9%99%A4%E6%96%B9%E6%B3%95%E5%92%8C%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9/

2021年1月20日 星期三

php 利用ssh執行遠端或本地liunx伺服器命令

PHP function ssh2_connect is not working

sudo apt-get install php-ssh2 && sudo /etc/init.d/apache2 restart

sudo apt-get install libssh2-php && sudo /etc/init.d/apache2 restart



 function ssh_exec($host, $port = 22, $ssh_username, $ssh_password, $command) {

    $con = ssh2_connect($host, $port);

    $auth_methods = ssh2_auth_none($con, $ssh_username);

    if (in_array('password', $auth_methods)) {

        $auth_methods = ssh2_auth_password($con, $ssh_username, $ssh_password);

    }

    $stdout_stream = ssh2_exec($con, $command);

    $err_stream = ssh2_fetch_stream($stdout_stream, SSH2_STREAM_STDERR);


    stream_set_blocking($stdout_stream, true); 

    stream_set_blocking($err_stream, true);


    $result_stdout = stream_get_contents($stdout_stream);

    $result_error = stream_get_contents($err_stream);


    fclose($stdout_stream);

    fclose($err_stream);

    return array('result' => $result_stdout, 'error' => $result_error);

}

$result = ssh_exec('172.20.10.11' , 22, 'pi', 'xxx', 'cd /var/www && python3 /var/www/test2.py');

print_r( $result);


資料來源: https://www.itread01.com/content/1549220941.html

2021年1月13日 星期三

學會MACD找出你的黃金交叉

常在股海裡闖蕩的朋友們應該很常聽到 MACD 這四個英文字母,常常會聽到當快線 (DIFF) 向上穿越慢線 (MACD) 是黃金交叉代表買入訊號、快線向下跌穿慢線是死亡交叉代表賣出訊號這類的說法,這一篇會先介紹 MACD 技術指標是什麼?再來用 Python 的方式來實作 MACD 技術指標分析,對量化交易有興趣或想理解 MACD 技術指標的朋友們可別錯過啦~

MACD (Moving Average Convergence / Divergence) 中文為指數平滑移動平均線常會在技術分析中被提到也是投資人最常使用的分析指標之一,只要能理解快線 (DIF) 與慢線 (MACD) 的發散或收斂關係就能讓投資人迅速掌握一支股票的近出場時機,簡單來說:

快線 (DIF) 向上穿越慢線 (MACD) > 買進訊號 (黃金交叉)

快線 (DIF) 向下跌穿慢線 (MACD) > 賣出訊號 (死亡交叉)

指數移動平均線 (EMA)

在計算快線與慢線前需要先理解指數移動平均線 (EMA),指數移動平均線與均線 (MA) 最大的差異為:EMA 是有經過權重控制後得出,日期越接近現在的股價有越大的權重,對於時間較長遠的股價則給予較小的權重。EMA 就是透過不同天用不同大小權重計算後得出

快線 (DIF)

理解什麼是 EMA 後,就能快速理解快、慢線計算方式了。DIF 則是用兩個不同天期的 EMA 相減後得出。常用 26天作為長天期、12天作為短天期

DIF = EMA(12) - EMA(26)

慢線 (MACD)

計算出快線後,再用 9日的 DIF 再取一次 EMA 就是所謂的慢線 (MACD)

MACD = EMA(DIF, 9)

Step 1. 獲取資料

以台積電 (2330.TW) 為例,先透過 yfinance 獲取每日股價資料並以2020/08/01為起算日

import pandas as pd
import yfinance as yf

stock_num = "2330"
stockNo = "{}.TW".format(stock_num)
startDate = "2020-08-01"
stock = yf.Ticker(stockNo)
stock_df = pd.DataFrame(stock.history(start=startDate))
stock_df = stock_df.reset_index()
print("參考交易日天數: {} 天".format(len(stock_df)))
stock_df.head()

Step 2. 計算快慢線

stock_df['EMA_12'] = stock_df['Close'].ewm(span=12, adjust=False).mean()
stock_df['EMA_26'] = stock_df['Close'].ewm(span=26, adjust=False).mean()
stock_df['DIF'] = stock_df['EMA_12'] - stock_df['EMA_26']
stock_df['MACD'] = stock_df['DIF'].ewm(span=9, adjust=False).mean()
stock_df.head()

Step 3. 畫出圖表找出黃金交叉

這邊將股價走勢與 MACD 線圖結合,方便讀者看出股價與 MACD 變化關係。從範例圖中可以看出當黃線向上穿越橘線時即是黃金交叉同時股價走揚,反之則為死亡交叉股價開始向下反轉

import matplotlib.pyplot as pltfig, ax1 = plt.subplots()
fig.set_size_inches(20, 6)
plt.title('MACD by Mr.HandByHand')
plt.xlabel('Date')
ax2 = ax1.twinx()
# macd & dif
ax1.set_ylabel('MACD', color='black')
ax1.plot(stock_df['Date'], stock_df['DIF'], color='gold', label="DIF", alpha=1)
ax1.plot(stock_df['Date'], stock_df['MACD'], color='coral', label="MACD", alpha=1)
ax1.legend(loc="lower left")
ax1.tick_params(axis='y', labelcolor='black')
ax1.grid(True)
# price
ax2.set_ylabel('Price', color='black')
ax2.plot(stock_df['Date'], stock_df['Close'], color='black', label="Price", linestyle=':', alpha=0.8)
ax2.legend(loc="upper left")
ax2.tick_params(axis='y', labelcolor='black')
fig.autofmt_xdate()
fig.show()

台積電 2330 MACD

2330 MACD 範例圖 

資料來源: https://mrhandbyhand.medium.com/python-macd-indicator-find-golden-cross-b876abcfe2d7

在樹莓派 RaspBerry Pi 執行排程Python程式 (cron / crontab)

工作環境:

  • RaspBerry Pi 3 Mode B+
  • 作業系統:版本代號為 Buster (Version:June 2019 / Release date:2019-06-20 / Kernel version:4.19)

樹莓派排程工作的編輯:

  1. 如何進入排程工作的編輯?
    (要用預設登入帳號pi的身分執行,所以不要sudo)
     crontab -e
  2. crontab -e的編輯器預設為nano:
    存檔:^O (ctrl-O)
    離開:^X (ctrl-X)
  3. 加入一個排程工作
    */5 * * * * python3 /home/pi/Programs/testSchedule.py > /dev/null 2>&1 
  4. 排程時間參數說明:
    (第幾分鐘 ) (幾點) (哪一天) (月份) (星期)
  5. 常用排程執行週期格式:
    • 每五分鐘執行一次:
       */5 * * * *
    • 每整點執行一次:
       0 * * * * 
    • 每天23:55執行一次:
      55 23 * * *
    • 每月1日00:05執行一次:
      5 0 1 * *
    • 每週一07:00執行一次:
      0 7 * * 1
    • 每小時的1,10,21,32,43,55
      "1,10,21,32,43,55" * * * *
    • 每月的1-3日06:10個執行一次
      10 6 1-3 * *
  6. 排程工作內容編輯後,必須重新啟動排程服務
    sudo service cron restart

用於排程的Python Script程式,須注意的事項:

  1. 用於排程的Python script程式,第一行(shebang line, #! 程式檔名)需指定,這個script要用哪個程式來執行,依照作業環境的不同,區分如下:
    • Windows:#! python3
    • OS X:#! /usr/bin/env python3
    • Linux:#! /usr/bin/python3
    • 其他Linux常見的shebang
      • #!/bin/sh→使用 sh(Bourne shell) 或其它相容 shell 執行指令碼
      • #!/bin/csh→使用 csh(C shell) 執行
      • #!/usr/bin/perl -w→使用帶警告的 Perl 執行
      • #!/usr/bin/python -O→使用具有程式碼最佳化的 Python 執行
      • #!/usr/bin/php→使用 PHP 的命令列直譯器執行
  2. 確認Python script程式的執行權限:
    • 將 .py 程式,放在 預設使用者 pi 的 home folder
    • 授予執行權限:chmod +x thePythonScript.py
    • python script排程時間指定的範例:
      每逢1月2日的03:04am 執行
      4 3 2 1 8 /home/pi/schedulePython.py

 

資料來源: https://books.bod.idv.tw/2019/07/raspberry-pi-cron-crontab.html



本篇介紹如何在 Linux 系統上使用 crontab 工作排程,設定讓系統定時自動執行指定的指令或程式。

Linux 的管理者或使用者如果需要定期執行某些指令或程式,最常見的方式就是使用 cron 來幫忙管理例行性工作排程,只要設定好 crontab 設定檔之後,系統就會自動依照設定的時間,定期執行重複性的工作。

查看與編輯 crontab

在 Linux 系統上,每一位使用者都可以自訂自己的 crontab 排程工作,若要查看自己的 crontab 內容,可以使用 crontab 指令加上 -l 參數:

crontab -l

如果是系統管理者要查詢特定使用者的 crontab 的話,可以使用 -u 參數指定使用者名稱:

sudo crontab -u gtwang -l

若要編輯自己的 crontab 內容,可以加上 -e 參數:

crontab -e

系統管理者若要編輯特定使用者的 crontab 內容,同樣是加上 -u 參數並指定使用者即可:

crontab -u gtwang -e

若要刪除目前所有的 crontab,可以使用 -r 參數:

crontab -r

個人 crontab 設定

在個人的 crontab 設定中,基本上每一行設定就代表一個要定期執行的程式,其格式如下:

MIN HOUR DOM MON DOW CMD

一行設定包含六個部分,各部分的意義如下:

欄位說明可設定的值
MIN分鐘0 到 59
HOUR小時0 到 23
DOM1 到 31
MON月份1 到 12,此欄位亦可用英文簡稱取代,例如一月也可以寫 Jan
DOW星期幾0(週日)到 6(週六),7 也代表週日。此欄位亦可用英文簡稱取代,例如週日也可以寫 Sun
CMD要定期執行的指令任何可執行的程式或指令稿(包含參數),例如 /path/to/cmd --your --parameter

除了一般的數字之外,crontab 亦可使用一些特殊字元,每個特殊字元都有不同的意義與適用情況:

特殊字元代表意義
星號(*代表接受任意時刻,例如若在月份那一欄填入星號,則代表任一月份皆可。
逗號(,分隔多個不同時間點。例如若要指定 3:00、6:00 與 9:00 三個時間點執行指令,就可以在第二欄填入 3,6,9
減號(-代表一段時間區間,例如若在第二欄填入 8-12 就代表從 8 點到 12 點的意思,也就是等同於 8,9,10,11,12
斜線加數字(/nn 代表數字,這樣寫的意思就是「每隔 n 的單位」的意思,例如若在第一欄填入 */5 就代表每間隔五分鐘執行一次的意思,也可以寫成 0-59/5

由於 crontab 設定的欄位有點多,不常用的人通常都記不住,建議在編輯 crontab 時,可以將以下的註解貼在設定檔內,方便參考。



以下是一些最基本的 crontab 設定範例。

30 08 * * * /home/gtwang/script.sh --your --parameter


30 18 * * 0 /home/gtwang/script.sh --your --parameter


30 18 * * Sun /home/gtwang/script.sh --your --parameter


30 08 10 06 * /home/gtwang/script.sh --your --parameter


30 21 1,15,29 * * /home/gtwang/script.sh --your --parameter


*/10 * * * * /home/gtwang/script.sh --your --parameter


00 09-18 * * * /home/gtwang/script.sh --your --parameter

系統設定檔

除了一般使用者各自的排程工作之外,的還有一類的是屬於系統的排程工作,這類的設定寫在 /etc/crontab 檔案與 /etc/cron.d/ 目錄下的各個設定檔中。

系統的 crontab 設定檔內容跟普通使用者的 crontab 類似,不過多了一個使用者名稱的欄位:

MIN HOUR DOM MON DOW USER CMD

例如每小時以 gtwang 帳號權限執行一次,則可以這樣寫:

0 * * * * gtwang /home/gtwang/script.sh --your --parameter

在系統的 crontab 設定檔中,只是多了一個使用者的欄位,其餘的設定方式都跟一般使用者的 crontab 相同。

特殊排程規則

crontab 除了以標準的格式撰寫排程工作之外,他也有提供幾個常用的特殊排程規則,這種特殊排程規則都以 @ 開頭,以下是每個特殊排程規則的說明:

排程規則說明
@reboot每次重新開機之後,執行一次。
@yearly每年執行一次,亦即 0 0 1 1 *
@annually每年執行一次,亦即 0 0 1 1 *
@monthly每月執行一次,亦即 0 0 1 * *
@weekly每週執行一次,亦即 0 0 * * 0
@daily每天執行一次,亦即 0 0 * * *
@hourly每小時執行一次,亦即 0 * * * *

例如每天執行一次,就可以這樣寫:

@daily /home/gtwang/script.sh --your --parameter

Email 通知設定

crontab 預設會將執行程式的輸出以 Email 送給執行的使用者,若要更改收件者,可以使用 MAILTO 變數指定:

MAILTO=gtwang


30 08 * * * /home/gtwang/script.sh --your --parameter

如果不想讓 crontab 寄送任何 Email 出來,可將 MAILTO 設定為空字串:

MAILTO=""


30 08 * * * /home/gtwang/script.sh --your --parameter

執行 Shell

若要更改執行工作的 Shell 環境,可以使用 SHELL 來指定要使用的 Shell:

SHELL=/bin/sh


30 08 * * * /home/gtwang/script.sh --your --parameter

限制使用者使用 crontab

由於系統安全性的考量,我們可能會希望限制只有特定的使用者可以使用 crontab,這時候就可以透過系統的 /etc/cron.allow 或 /etc/cron.deny 兩個檔案來設定。

/etc/cron.allow
如果這個檔案存在,則只有被列在這裡的帳號可以使用 crontab,其餘帳號皆禁止使用,也就是白名單。
/etc/cron.deny
如果這個檔案存在,則被列在這裡的使用者都禁止使用 crontab,也就是黑名單。

/etc/cron.allow 與 /etc/cron.deny 設定檔在列出帳號時,語法都相同,每一行寫一個帳號名稱。

如果 /etc/cron.allow 與 /etc/cron.deny 兩個設定檔都不存在,則就只有系統管理者 root 能夠使用 crontab

資料來源: https://blog.gtwang.org/linux/linux-crontab-cron-job-tutorial-and-examples/

2021年1月11日 星期一

Linux 常用 command


List process
ps -ef |grep test2

刪除 all process
pkill -9 -f test2.py 

2021年1月7日 星期四

Linux Raspberry pi Wi-Fi 自動連線、DNSDynamic 網址

配置你的網路連線的其中一個方法就是去手動配置你的網絡卡介面配置檔案。使用你用的比較順手的一個檔案編輯器(哥習慣的是vi)來開啟該介面設定檔案:

sudo vi /etc/network/interfaces

把該配置檔案修改成DHCP連線模式如下所示:

1 auto lo
2 
3 iface lo inet loopback
4 iface eth0 inet dhcp
5 
6 allow-hotplug wlan0
7 iface wlan0 inet dhcp
8 wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
9 iface default inet dhcp

下一步你需要做的就是去提供你的WiFi網路連線資訊。請開啟你的WPA配置檔案如下:

sudo vi /etc/wpa_supplicant/wpa_supplicant.conf

下面給出了我的一個配置示例以供參考:

 1 ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
 2 update_config=1
 3 network={
 4   ssid="ENTER NETWORK NAME"
 5   proto=WPA
 6   key_mgmt=WPA-PSK
 7   pairwise=TKIP
 8   psk="ENTER WPA KEY"
 9   auth_alg=OPEN
10 }

如果你不想使用DHCP或者說你想要設定多個網路連線的話,那麼你就需要一些額外的設定。比如你需要做如下修改:

iface wlan0 inet dhcp => iface wlan0 inet manual

並且做如下修改:

wpa-conf => wpa-roam

下面同時給出了一個靜態IP配置的示例:

1 auto lo
 2 
 3 iface lo inet loopback
 4 iface eth0 inet dhcp
 5 
 6 allow-hotplug wlan0
 7 iface wlan0 inet manual
 8 wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
 9 iface default inet dhcp
10 
11 # For ssid 'work':
12 iface work inet static
13 address XXX.XXX.X.X
14 network XXX.XXX.X.X
15 gateway XXX.XXX.X.X

你將需要在你的WPA設定中輸入你的工作網路資訊:

 1 ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
 2 update_config=1
 3 network={
 4   ssid="ENTER NETWORK NAME"
 5   proto=WPA
 6   key_mgmt=WPA-PSK
 7   pairwise=TKIP
 8   psk="ENTER WPA KEY"
 9   auth_alg=OPEN
10 }
11 network={
12   ssid="work"
13   proto=WPA
14   key_mgmt=WPA-PSK
15   pairwise=TKIP
16   psk="ENTER WPA KEY"
17   auth_alg=OPEN
18 }

然後重啟:

sudo shutdown -r now

如果你的設定是正確的話那麼你現在的網路連線應該就是OK的了。你可以通過以下命令來進行驗證:

ifconfig

在你的wlan0這個輸出中你會看到一個分配的IP如下所示: 'inet addr:XXX.XXX.XXX.XXX'

如果你想在不用重啟的情況下就進行驗證的話,你可以先通過以下方式釋放已有的網路連線:

sudo ifdown wlan0

然後通過以下命令來使用新配置進行連線:

sudo ifup wlan0

讓樹莓派告訴你它的IP(軟體的方式)

那麼如何在你的樹莓派加入新的網路後獲取到它當前的ip地址呢?因為你在重新配置樹莓派的網路並重啟後,你跟樹莓派的連線會斷掉,因此你需要知道樹莓派在新網路中的ip,從而使你能重新連線到樹莓派。在網上很多免費提供的域名解析服務,你可以某個域名解析成你設定的ip地址。每次樹莓派啟動後都會更新自己的域名對應的ip,我是用的DNSDynamic提供的服務,進行簡單的設定就OK了。

  1. 註冊賬號~~~~
  2. 設定一個啟動指令碼來獲取本機ip並且更新到DNSDynamic上:

    • 修改/etc/rc.local,新增如下內容:

      IP=`hostname -I`
      EMAIL=your_username_in_dnsdynamic
      PASSWORD=your_password
      DOMAIN=your_registered_domain.dnsdynamic.com
      curl -v --user "$EMAIL:$PASSWORD" -k "https://www.dnsdynamic.org/api/?hostname=$DOMAIN&myip=$IP" > /var/log/update-dns.log 2>&1
      

指令碼後面的內容是呼叫dnsdynamic提供的api更新域名對應的ip地址

每一次樹莓派啟動之後都會執行這個指令碼更新自己的ip地址,也可以將這段腳新增到cron job裡定時更新ip,但是感覺好像沒有必要。

  1. 之後你就不用管ip地址了,可以通過域名直接ssh進樹莓派:

    ssh pi@your_registered_domain.dnsdynamic.com
    

 


Linux 使用UUID在fstab掛載

現場(環境):Redhat 7.7    指令:blkid


*使用UUID 來寫入fstab最大的好是,他會跟硬碟順序無關。

一般來說我們DISKlinux內會被區分為sdasdb…

若硬碟順序遭到替換,這個在Linux fstab掛載時會一部分影響我們的運作

*所以會有多數人建議使用UUID來替換原先的名稱定義。

*UUID數值是我們透過mkfs在做硬碟的格式化的時候被定義好的。

*另外的LABEL掛載方式可以參考[參考網址]

我們查看我們的fstab可以看到,在原生我們分割好的系統當中。

/boot這個重要的指標已經用UUID的方式來進設定。

*這也是為了讓硬碟順序變更時不會被影響。

#vim /etc/fstab

圖片

*其他的/dev/mapper/XXX 大家會覺得怎麼跟當初自己分割LV時的名稱不一樣,其實我們可以去查看。

圖片

我們會發現他們都一樣是被指向dm-0

我們的分割區都是被指向這些地方。

圖片

所以為了避免這個順序因為硬體變更而遭受影響,

所以會以唯一值的UUID進行掛載。

接著我們透過UUID來試著進行掛載。


先透過blkid指令查詢每個分割區格式化後取得的UUID值。

這邊會發現除了mkfs格式化外,

在進行fdisk指令分割硬碟時,硬碟分割區也會取得唯一值。

*也可以注意到 fstab /bootUUID/dev/sda1UUID是相同的。

圖片

取得格式化後的LV{/dev/mapper/XXXX}的唯一值之後,

我們就可以開始更改fstab的內容。

*這邊已另外一個分割區來進行測試

=!======================

UUID={blkid指令查詢到的這個分割區UUID} {掛載點} {格式化} defaults 0 0

=!======================

圖片

更改後我們先卸載掉分割區測試看看。

原本掛載點內有這幾個資料夾。

圖片

將掛載點卸載掉

圖片


重新掛載測試看看

*可以透過mount -a,這個指令還會幫你判斷你的fstab內填寫的是否正確。

*測試結果可以看到,透過UUID的方式我們也能夠正常的掛載

圖片


Extra: <參考參考網址>

雖然UUID是唯一值,但是是可以透過後面的動作在做修改的。

*必須為非XFS格式 (tune2fs只支援ext2-ext4)

手動改變UUID (記得先記錄原本的UUID)

但這個手動的方式,我們必須使用特別的方法來執行。

*雖然是可以手動改,但也要是Linux內可以辨認的,

所以必需透過uuidgen生成一個隨機的UUID(合法)

#uuidgen

圖片

#uuidgen | xargs tune2fs /dev/sdb1 -U

如果有狀況,我們就用下列方法把原本的UUID寫回去。

#tune2fs -U {手動輸入UUID數值} /dev/sdb1

一般mount掛載的方式也比較特別,會需要帶上UUID=的告知。

#mount UUID="{UUID數值}" /var

#mount -U "{UUID數值}" /var


Mount FAT32 with read write permissions
/dev/sdb1 /media/drive1 vfat dmask=000,fmask=0111,user 0 0


參考網址:

https://www.itread01.com/content/1548894797.html

https://support.huaweicloud.com/usermanual-ims/ims_01_0325.html

https://ssorc.tw/1313/linux-%E4%BD%BF%E7%94%A8-uuid-%E4%BE%86%E6%8E%9B%E8%BC%89%E7%A1%AC%E7%A2%9F/

https://access.redhat.com/documentation/zh-tw/red_hat_enterprise_linux/6/html/installation_guide/apcs04s07

https://www.itread01.com/content/1549958233.html

https://unix.stackexchange.com/questions/259298/use-tune2fs-on-xfs-filesystem-get-couldnt-find-valid-filesystem-superblock 


資料來源: https://it001.pixnet.net/blog/post/359638481-it%E4%BA%8B%E4%BB%B6%E7%B0%BF-%E4%BD%BF%E7%94%A8uuid%E5%9C%A8fstab%E6%8E%9B%E8%BC%89