---
# System prepended metadata

title: LINE BOT課程常見問題

---

# LINE BOT課程常見問題

# 最難調試排行榜
## <a href="#Verify後-404-NOT-FOUND" style="color: black; text-decoration: underline">No.1 Verify後 `404 NOT FOUND`</a>
#### 請把 `@app.route("/callback", methods=['POST'])` 改成 `@app.route("/", methods=['POST'])`
#### 或將Webhook URL後`/`變成`/callback`
## <a href="#PY程式或gunicorn運行時失敗" style="color: black; text-decoration: underline">No.2 沒關翻譯器就複製 ACCESS TOKEN</a>
## <small>No.3 (從缺)</small>

# 速覽
[TOC]

# 本筆記的約定

## 我們將使用`<>`表示需要替換的地方
## 部分問題含有內文可以深入認識
# 大部分的資料來源
#### `<命令> --help`
#### `help <命令>`
#### `man <命令>`
#### `info <命令>`

# WSL相關
## adduser: Please enter a username matching the regular expression configured
#### WSL使用者名稱只允許\[小寫英文字母\]、\[0~9\]、\[_\]、\[-\]，且不超過32個字元
## \<username\> is not in the sudoers file. 
#### 在cmd或powershell輸入 `wsl -u root` 並輸入 `usermod -aG sudo <username>`，並關閉所有wsl，等待8秒後(自動關機wsl)重啟wsl，你也可以在cmd或powershell執行`wsl --shutdown`來手動關機

# Linux 內建命令



## rm: cannot remove '資料夾': Is a directory
#### 當你嘗試刪除一個包含內容的資料夾時，就會報錯，運行 rm -rf <資料夾路徑>
`-r`,`-R`,`--recursive` 表示「遞迴」刪除資料夾內資料夾與檔案
`-f`,`--force` 為強制
有些需要強制刪除者可使用`-rf`跳過

## 別把`cat`和`ls`、`cd`用錯對象
#### `cat`負責輸出檔案內容，`ls`負責輸出資料夾內部，`cd`負責進入資料夾

# 應用相關

## 我打開了個未知的文檔查看器，我該如何退出
#### 這通常是vi/vim系列，`:q`即可

## 如何儲存與退出nano
#### 儲存: Ctrl+O / 退出: Ctrl+X

# 伺服器相關

## 如何查看已使用空間
#### quota -s 或 du -hs ~
`quota`意指"扣打"，也就是配額
`-s`或`--human-readable[=units]` 會使用如K,M,G等單位顯示

此指令會有如下輸出
```
     Filesystem   space   quota   limit   grace   files   quota   limit   grace
      /dev/sda1  59188K    100M    100M            4279       0       0
```
space是當前使用量，quota和limit為最大限制，歡迎在留言區補充這兩個的差別

`du [FILE]...` 會輸出檔案或遞迴計算資料夾的使用空間
`-h`或`--human-readable[=units]` 會使用如K,M,G等單位顯示
`-s, --summarize` 不會一一列出資料夾中各檔案、資料夾與自身的空間，而只有自身的空間

## 設定權限
#### chmod <擁有者權限(0-7)><群組權限(0-7)><訪客權限(0-7)> <檔案>
#### 網站權限設置：chmod 755 ~/www/

## 如何在無法sudo下安裝套件
#### https://askubuntu.com/a/350
舉個例子，倘若我們想要安裝`tree`
```bash
apt download tree
dpkg-deb -x tree*.deb tree_deb
```
以下是`tree_2.0.2-1_amd64.deb`的結構
```
tree_deb
└── usr
    ├── bin
    │   └── tree
    └── share
        ├── doc
        │   └── tree
        │       ├── README.gz
        │       ├── TODO
        │       ├── changelog.Debian.gz
        │       └── copyright
        └── man
            ├── fr
            │   └── man1
            │       └── tree.1.gz
            └── man1
                └── tree.1.gz
```
其中`tree_deb/usr/bin/tree`就是我們想要的可執行檔，而且幸運的是，tree的依賴項`libc6`已經安裝且此程式很簡單，直接運行：
```bash
mv tree_deb/usr/bin/tree ~/.local/bin/
```
- 移動到此目錄的原因是`PATH`這個系統尋找執行檔的環境變量包含此路徑
    - 你可以透過`echo $PATH`得知PATH包含的
- `apt-cache depends <package>`可查看依賴項
- `apt show <package>`可查看包詳情
- `apt search <keyword>`可查詢包
- `dpkg -l [<pattern>...]`可確認是否已安裝某包
- `dpkg-deb -x <deb> <dir>`可將一個deb包提取到dir資料夾中

# Python相關

## Command 'python' not found
#### 請改為`python3`或運行`sudo rm /usr/bin/python && ln -s /usr/bin/python3 /usr/bin/python`

## .PY程式或gunicorn運行時失敗
#### 確定程式複製完整
#### 括號、引號不要漏、都必須成雙成對
#### TOKEN、SECRET確定和LINE開發者網頁顯示一致
#### gunicorn和ngrok的port必須一致
#### <div style="background-color: black; color: red"><b>\>注意事項\< </b><br></b><div>關掉翻譯器再複製ACCESS TOKEN、SECRET

## 為甚麼我不能用`venv`、`act`、`deact`
#### 要在~/.bashrc 加入alias指令
```bash
alias venv='python -m venv'
alias act='source .venv/bin/activate || source bin/activate
alias deact='deactivate'
```
`alias: alias [-p] [name[=value] ... ]`
本指令可用於縮減指令，本質上是一個變數調用
#### <div style="background-color: black; color: red"><b>>注意事項<</b><br>bash中，是不允許`=`兩邊加空格的，程式一般以空格區隔引數</div>
 

## 開啟activate時報錯
#### 請改用`source <path>/bin/activate`開啟

# AI 相關
## Verify後 `404 NOT FOUND`
#### 請把 `@app.route("/callback", methods=['POST'])` 改成 `@app.route("/", methods=['POST'])`
#### 或將Webhook URL後`/`變成`/callback`

ChatGPT: https://chat.openai.com/share/baccb0db-b0c0-4736-8d7f-33af48bf559c
Bard: https://g.co/bard/share/915f362d0674
Claude: (代碼和邏輯與ChatGPT相差不遠)

關於這件事來自ChatGPT和Claude，Bard不知道在幹嘛
由於[Github的v2示例](https://github.com/line/line-bot-sdk-python/blob/3e5d4b6de67875ad40453b6b62d13d29d4baf2a1/examples/flask-echo/app.py)使用`callback`為Flask路徑，而不是我們給的示例`/`，所以callback的地方不同，就會報Error 404，gunicorn也接收不到，這就是我將它放在第一名的原因。

# gunicorn/ngrok相關

## 如何殺掉gunicorn
#### killall -u $(whoami) gunicorn

`-u USER` 代表尋找由`USER`運行的進程
`whoami` 會輸出使用者名字
`"$(command)"`會運行command並將回傳的值取代掉這一串指令

## 如何查看gunicorn是否運行
#### `pgrep -a gunicorn`

`pgrep <pattern>`是一個用來查找process的指令，`grep`從`ed`的同效輸出`g/re/p`來命名的<sup><a href="https://w.wiki/87oQ">[1]</a></sup>
預設會印出PID<small>(<b>P</b>rocess <b>Id</b>entifier)</small>
`-a`或`--list-full` 會輸出process的完整指令
`-u <ID,...>`或`--euid <ID,...>`可以匹配用戶，可搭配`id -u`匹配自己

## 如何調試gunicorn
#### `killall -u $(whoami) gunicorn`，並在運行gunicorn時去掉` --daemon`

## gunicorn運行時ModuleNotFoundError
#### 確保已經進入虛擬環境(venv)，並已安裝插件

虛擬環境啟動命令
```
source <venv_path>/bin/activate
```

Module安裝命令
```
pip install Flask line-bot-sdk gunicorn
```

## ngrok 502 error
#### GUNICORN和NGROK的PORT設定不一致
#### 沒有驗證NGROK([官網](https://ngrok.com/))

## [ERROR] Can't connect to ('127.0.0.1', 8000)
#### 表示啟用了多個gunicorn並引起port衝突

# 考試相關
#### 本機要運行gunicorn和ngrok，Line Webhook URL填ngrok給的網址；伺服器端只要跑gunicorn，Line Webhook URL打`https://app1.********/531xx/`
