跳至主要內容

部落格環境遷移

我們已將部落格環境從 Jekyll 遷移至 Docusaurus。 我們計劃將 Jekyll 中點閱率較高的文章一併移轉過來。

在 Python 偵測極值

摘要

偵測訊號的極值。

訊號的產生

舉例產生一個偽造的訊號。

  • 3 [Hz] 的訊號 + 0.01 [Hz] 的訊號 + 雜訊
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from scipy import signal

t = np.arange(30 * 100) / 100
x = np.sin(2 * np.pi * t / 3) + np.random.randn(len(t)) * 0.2 + np.sin(2 * np.pi * t / 100)
df = pd.DataFrame({'Data': x}, index=pd.to_datetime(t, unit='s').time)

fig, ax = plt.subplots()
df.plot(ax=ax, xlim=['00:00:00', '00:00:10'])
plt.show()

tmp

檢查訊號的特性

def acorr(df: pd.DataFrame, ra: int = 3, fs=100):
x = np.correlate(df.Data.values, df.Data.values, mode='full')
t = (np.arange(len(x)) - len(x) / 2 + 0.5) / fs
x /= x.max()
fig, ax = plt.subplots()
ax.set_xlim(-ra, ra)
ax.set_ylim(0, 1)
ax.plot(t, x)
ax.set_title('Autocorrelation')
ax.grid(axis='x')
ax.set_xticks(np.linspace(-ra, ra, 2 * ra + 1))
plt.show()

acorr(df)

可以看出主要的訊號是 1/3 [Hz]。因此,對 1/3 [Hz] 施加低通濾波器。

tmp

套用低通濾波器並偵測極值

套用低通濾波器以便偵測極值。

如果在 1/3 [Hz] 施加低通濾波器仍無法正確偵測,請逐步降低頻率。

tmp

fs = 10
lpf = 0.1
b, a = signal.butter(5, lpf / fs * 2, 'low')
df['Filter'] = signal.filtfilt(b, a, df.Data.values)
max_idx = signal.argrelmax(df['Filter'].values)
min_idx = signal.argrelmin(df['Filter'].values)

df['max_index'] = False
df.iloc[max_idx[0], 2] = True
df['min_index'] = False
df.iloc[min_idx[0], 3] = True

fig, ax = plt.subplots()
df.plot(ax=ax)
ax.set_xlim(['00:00:00', '00:00:30'])
ax.scatter(
df.loc[df['max_index'], ['Filter']].index,
df.loc[df['max_index'], ['Filter']],
color='tab:orange',
zorder=3)
ax.scatter(
df.loc[df['min_index'], ['Filter']].index,
df.loc[df['min_index'], ['Filter']],
color='tab:green',
zorder=3)
plt.show()

C 語言的二維陣列處理

用結構體將行數、列數與儲存數值的記憶體整合在一起,會更方便操作。

#include <stdio.h>
#include <stdlib.h>

typedef struct {
float *data;
int col_size;
int row_size;
} Mat;

void MatInit(Mat *mat, int row_size, int col_size) {
mat->row_size = row_size;
mat->col_size = col_size;
mat->data = (float *)calloc(row_size * col_size, sizeof(float));
}

float *MatAt(Mat *mat, int i, int j) {
return mat->data + i * mat->col_size + j;
}

void MatFree(Mat *mat) { free(mat->data); }

int main(void) {
Mat mat;
MatInit(&mat, 30, 5); // 初始化 30 行 5 列的矩陣
*MatAt(&mat, 0, 0) = 50; // 將第 0 行第 0 列設為 50
printf("%f\n", *MatAt(&mat, 0, 0)); // 顯示第 0 行第 0 列的數值

MatFree(&mat);

return 0;
}

從安裝腳本中得到錯誤的結果

這篇備忘錄記錄了當我從安裝腳本中得到錯誤結果時的解決方法。


問題描述

有時,當我運行某些安裝腳本(例如來自 GitHub 的自動安裝腳本或官方提供的 install.sh)時,會遇到以下錯誤信息:

Got bad result from install script

這個錯誤通常表示腳本執行不成功,或者沒有返回預期的成功代碼。這可能是由於多種原因造成的,例如:

  • 網絡問題:下載資源失敗。
  • 權限問題:腳本沒有足夠的權限執行某些操作。
  • 依賴缺失:系統中缺少腳本所需的工具或庫。
  • 環境不兼容:腳本是為不同環境設計的,或者當前環境變量不正確。
  • 腳本本身的問題:腳本有 bug。

解決方案

1. 檢查網絡連接

確保你的設備連接到互聯網,並且沒有任何防火牆或代理設置阻止腳本訪問外部資源。

ping google.com

2. 檢查權限

確保你以正確的權限運行腳本。對於需要系統級更改的腳本,通常需要使用 sudo

sudo bash install.sh

3. 安裝缺失的依賴

仔細閱讀腳本的輸出,查找是否有關於缺少命令或庫的錯誤信息。通常,腳本作者會在 README 中列出先決條件。

常見的依賴包管理器命令:

  • Ubuntu/Debian:sudo apt install <package_name>
  • CentOS/Fedora:sudo yum install <package_name>sudo dnf install <package_name>
  • macOS (Homebrew):brew install <package_name>

4. 檢查環境變量

某些腳本依賴特定的環境變量。確保你的 PATH 設置正確,並且所有必要的環境變量都已導出。

你可以使用 env 命令查看當前的環境變量。

5. 逐行執行腳本 (調試)

如果上述方法都無效,你可以嘗試逐行執行腳本,以找出問題的確切位置。

  1. 打開腳本
    vim install.sh
  2. 在腳本開頭添加 set -x: 這會讓 Shell 打印出每個執行的命令,幫助你追蹤問題。
    #!/bin/bash
    set -x
    # ... 腳本其餘內容
  3. 運行腳本:觀察輸出,當腳本失敗時,最後一個打印的命令通常是導致問題的原因。

6. 查閱腳本的 GitHub 頁面或文檔

如果腳本來自開源項目,請訪問其 GitHub 儲存庫。查看 Issues 頁面,看看是否有其他人遇到過相同的問題,或者在 Wiki/文檔中查找是否有特定的故障排除指南。

7. 嘗試不同的安裝方式

如果腳本提供的安裝方式失敗,看看項目是否提供了替代的安裝方式,例如:

  • 手動編譯
  • Docker 容器
  • 包管理器安裝(如 apt, yum, brew, npm, pip 等)

總結

遇到 "Got bad result from install script" 錯誤時,不要慌張。系統地檢查網絡、權限、依賴和環境變量,並利用調試工具,通常可以找到問題的根源並解決它。

NMF (HALS) 的實作

import numpy as np

X = np.array([[1, 1], [2, 1], [3, 1.2], [4, 1], [5, 0.8], [6, 1]])

n_components, n_samples, n_features, = (2,) + X.shape
W = np.random.uniform(size = (n_samples, n_components))
H = np.random.uniform(size = (n_components, n_features))

eps = 1e-4

# NMF
for i in range(100):
# update B
A = X.T.dot(W)
B = W.T.dot(W)
for j in range(n_components):
tmp = H[j, :] + A[:, j] - H.T.dot(B[:, j])
H[j, :] = np.maximum(tmp, eps)

# update A
C = X.dot(H.T)
D = H.dot(H.T)
for j in range(n_components):
tmp = W[:, j] * D[j, j] + C[:, j] - W.dot(D[:, j])
W[:, j] = np.maximum(tmp, eps)
norm = np.linalg.norm(W[:, j])
if norm > 0:
W[:, j] /= norm

print(W)
print(H)
print(W.dot(H))

在 brew 環境下無法安裝 nokogiri 時的解決方法

發生了以下兩個錯誤:

zlib is missing; necessary for building libxml2
xslt is missing. Please locate mkmf.log to investigate how it is failing.

解決方法

  • 安裝 libxslt 與 libxml2
  • 指定 brew 安裝的 libxml2 路徑
brew install libxslt libxml2
bundle config build.nokogiri --use-system-libraries --with-xml2-include=$(brew --prefix libxml2)/include/libxml2

參考網站

WSL 上的 DNS 配置

這篇備忘錄記錄了在 WSL(Windows Subsystem for Linux)上配置 DNS 的方法。

資訊

WSL 允許你在 Windows 上運行 Linux 環境,但有時網絡配置(尤其是 DNS)可能會遇到問題。了解如何正確配置 DNS 可以確保你的 WSL 環境能夠正常解析域名。

WSL 中的 DNS 工作原理

默認情況下,WSL 會嘗試從 Windows 主機獲取 DNS 配置。這通常是通過在 WSL 虛擬機中生成 /etc/resolv.conf 文件來實現的。這個文件通常包含一個指向 Windows DNS 服務的 IP 地址,例如 172.X.X.X

常見問題

  • 無法解析域名:這是最常見的問題,表現為無法訪問互聯網或特定服務。
  • DNS 解析速度慢:有時默認配置會導致 DNS 查詢變慢。

解決方法

方法 1:禁用 /etc/resolv.conf 的自動生成 (推薦)

WSL 每次啟動時都會自動重新生成 /etc/resolv.conf。禁用此功能可以讓你手動配置 DNS。

  1. 創建或編輯 wsl.conf 文件

    在 WSL 環境中,創建或編輯 /etc/wsl.conf 文件:

    sudo vim /etc/wsl.conf

    添加以下內容:

    [network]
    generateResolvConf = false

    保存並退出。

  2. 重啟 WSL

    在 PowerShell 或 CMD 中,終止 WSL 以使其應用更改:

    wsl --shutdown

    然後重新啟動你的 WSL 發行版。

  3. 手動編輯 /etc/resolv.conf

    現在,你可以手動編輯 /etc/resolv.conf 並添加你喜歡的 DNS 服務器。例如,使用 Google DNS:

    sudo vim /etc/resolv.conf

    添加以下內容:

    nameserver 8.8.8.8
    nameserver 8.8.4.4

    保存並退出。

    :::warning 注意 如果你在 wsl.conf 中設置了 generateResolvConf = false/etc/resolv.conf 將不再被自動覆蓋。 :::

方法 2:在 Windows 中配置 DNS

WSL 從 Windows 繼承 DNS 設置,因此你也可以直接在 Windows 的網絡適配器設置中更改 DNS 服務器。

  1. 打開 網絡和 Internet 設置 -> 更改適配器選項
  2. 右鍵點擊你的網絡連接(例如 Wi-Fi 或乙太網),選擇 屬性
  3. 選擇 Internet 協議版本 4 (TCP/IPv4),然後點擊 屬性
  4. 選擇 使用下列 DNS 服務器地址,然後輸入你偏好的 DNS 服務器,例如 Google DNS (8.8.8.8 和 8.8.4.4)。
  5. 點擊 確定 保存更改。

重啟你的 WSL 發行版,它應該會自動獲取新的 DNS 設置。

方法 3:使用 netsh (Windows 命令)

在某些情況下,你可以使用 netsh 命令來重置或配置 Windows 的 DNS 緩存。

ipconfig /flushdns
netsh interface ip delete dns "乙太網" all
netsh interface ip add dns "乙太網" 8.8.8.8 index=1

將 "乙太網" 替換為你的實際網絡適配器名稱。

測試 DNS 解析

你可以使用 pingdig 命令來測試 DNS 解析是否正常工作:

ping google.com

sudo apt install dnsutils # 如果沒有安裝 dig
dig google.com

總結

通過禁用 /etc/resolv.conf 的自動生成並手動配置,或者直接在 Windows 中更改 DNS 設置,你可以有效地解決 WSL 中的 DNS 問題。選擇適合你的方法,以確保 WSL 環境的網絡連接穩定可靠。

Windows OpenSSH Permission denied 問題

  • 可以使用密碼登入(雖然設定中已停用)
  • 使用公鑰驗證時發生 Permission denied

連線至 localhost:22 時,出現以下錯誤:

hikari@localhost: Permission denied (publickey,keyboard-interactive).

image

原因

Administrators 群組(即「系統管理員使用者」)預設會從 C:\ProgramData\ssh\administrators_authorized_keys 讀取公鑰進行驗證。

需要將其改為 $env:userprofile\.ssh\authorized_keys

解決方法

以系統管理員權限開啟 C:\ProgramData\ssh\sshd_config,將以下兩行註解掉:

image

- Match Group administrators
- AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
+ #Match Group administrators
+ # AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

儲存後,重新啟動服務。

Restart-Service sshd

Termux 上的 Powerline

這篇備忘錄記錄了在 Termux 上安裝和配置 Powerline 的方法。

資訊

Powerline 是一個為各種 Shell(如 Bash、Zsh)和編輯器(如 Vim)提供美觀且功能豐富的狀態欄插件。它顯示有用的信息,如當前 Git 分支、Vim 模式、Python 虛擬環境等。

安裝步驟

1. 更新 Termux 套件

在安裝任何新軟體之前,建議先更新 Termux 的套件列表:

pkg update && pkg upgrade

2. 安裝必要的套件

Powerline 需要 Python 環境。此外,為了顯示特殊字元(如箭頭),你需要安裝一個支持 Powerline 字體。

pkg install python python-pip
pkg install git

3. 安裝 Powerline

使用 pip 安裝 Powerline:

pip install --user powerline-status

安裝完成後,Powerline 的可執行文件會位於 ~/.local/bin/

4. 配置 Shell

你需要將 Powerline 添加到你的 Shell 配置中。這裡以 Bash 為例。

編輯 ~/.bashrc 文件:

vim ~/.bashrc

在文件末尾添加以下內容:

# Powerline
export PATH="$PATH:$HOME/.local/bin"
powerline-daemon -q
POWERLINE_BASH_CONTINUATION=1
POWERLINE_BASH_SELECT=1
. ~/.local/lib/python*/site-packages/powerline/bindings/bash/powerline.sh

保存並退出,然後重新載入 ~/.bashrc

source ~/.bashrc

5. 安裝 Powerline 字體

為了讓 Powerline 正確顯示特殊字元,你需要一個 Powerline 字體。在 Termux 中,你可以直接安裝。

pkg install termux-api
termux-setup-storage

然後,你可以下載並安裝一個 Powerline 字體。由於 Termux 的環境限制,直接修改系統字體可能比較麻煩。一種常見的做法是使用支持 Powerline 的終端模擬器(如 Termux 的默認字體通常已支持)。

如果你在其他 Linux 環境下,你可以安裝 fonts-powerline

sudo apt install fonts-powerline

或者手動下載並安裝字體。

6. 配置 Powerline 主題 (可選)

Powerline 允許你自定義狀態欄的外觀。你可以創建自己的配置或修改現有的配置。

通常,配置文件位於 ~/.config/powerline/。你可以複製預設配置進行修改:

mkdir -p ~/.config/powerline
cp -r ~/.local/lib/python*/site-packages/powerline/config_files ~/.config/powerline/

然後編輯 ~/.config/powerline/config.json~/.config/powerline/themes/shell/default.json

總結

通過上述步驟,你可以在 Termux 上成功安裝和配置 Powerline,為你的命令行界面帶來更美觀和信息豐富的狀態欄。這將極大地提升你的終端使用體驗。

Termux 上的 SSH

這篇備忘錄記錄了在 Termux 上使用 SSH 的方法。

資訊

Termux 是一個 Android 上的終端模擬器和 Linux 環境應用程式,它允許你運行許多 Linux 命令和工具。SSH 是一種安全的網絡協議,用於在不安全的網絡上安全地執行網絡服務。

在 Termux 中,你可以將其作為 SSH 客戶端連接到遠端服務器,也可以將其設置為 SSH 服務器,以便從其他設備連接到你的 Android 設備。

1. 作為 SSH 客戶端

安裝 OpenSSH

Termux 提供了一個 OpenSSH 套件,你可以通過 pkg 命令安裝:

pkg update && pkg upgrade
pkg install openssh

連接到遠端服務器

安裝完成後,你可以使用 ssh 命令連接到遠端服務器:

ssh user@hostname_or_ip

例如:

你也可以使用 SSH 密鑰進行身份驗證,這比密碼更安全。

生成 SSH 密鑰

如果尚未生成,你可以在 Termux 中生成 SSH 密鑰對:

ssh-keygen

按照提示操作,通常可以直接按 Enter 使用默認值。公鑰會保存在 ~/.ssh/id_rsa.pub,私鑰在 ~/.ssh/id_rsa

上傳公鑰到遠端服務器

將你的公鑰複製到遠端服務器的 ~/.ssh/authorized_keys 文件中:

ssh-copy-id user@hostname_or_ip

或者手動複製:

cat ~/.ssh/id_rsa.pub | ssh user@hostname_or_ip "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

2. 作為 SSH 服務器

啟動 SSH 服務器

Termux 內置了一個 SSH 服務器。默認情況下,它在端口 8022 上運行。 要啟動 SSH 服務器,只需運行 sshd 命令:

sshd

:::warning 注意 每次 Termux 應用程式關閉或設備重啟後,你都需要重新運行 sshd 命令來啟動 SSH 服務器。 :::

設置 SSH 密碼

如果你想使用密碼連接,你需要為你的 Termux 用戶設置一個密碼:

passwd

輸入並確認你的密碼。

從其他設備連接

現在,你可以從你的電腦或其他設備連接到 Termux SSH 服務器。你需要知道你的 Android 設備在局域網中的 IP 地址。

在你的電腦上:

ssh -p 8022 user@android_device_ip

其中 user 是你的 Termux 用戶名(通常是 u0_aXXX 這樣的字串,但對於 Termux SSH 服務器,你可以直接使用 sshd 運行時的用戶名,通常是 root 或者你當前的 shell 用戶)。

查找 Termux 用戶名

你可以在 Termux 中運行 whoami 命令來查看當前用戶名。 更可靠的方法是,當你啟動 sshd 後,它會使用當前的用戶身份。如果你沒有顯式設置用戶,它可以是 root (如果你以 root 權限運行) 或者默認的 Termux 用戶。

停止 SSH 服務器

要停止 SSH 服務器,你可以找到 sshd 進程並終止它:

pkill sshd

總結

Termux 提供了強大的 SSH 功能,無論是作為客戶端還是服務器,都能極大地增強你的 Android 設備的實用性。這使得在手機上進行開發、遠端管理或其他基於 SSH 的任務變得可能。