# Linux Command & Cluster System
## ssh
透過 ssh protocal 連線到遠端機器
`ssh-keygen` 產生公私鑰,或是用 `ssh-copy-id` 幫你從 `ssh-keygen` 到 `ssh` 都直接做好。
產出來的公私鑰會儲存在 `~/.ssh` 當中
## Basic Commands
> 因為大多數原本就會了,所以就挑之前沒看過或值得補充的來講
### find
`find <搜尋根目錄> <其他參數>`
| args | meanings | example |
| :--------: | :--------: | :--------: |
| type | 尋找某一類型的檔案(e.g. `d`目錄,`f`一般檔案) | `find . -type f` (從現在這個資料夾下找一般檔案) |
| name | 以名稱搜尋 | `find . -name temp.cpp` (從現在這個資料夾下找`temp.cpp`) |
| perm | 搜尋特定權限 | `find . -perm 0777` (從現在這個資料夾下找權限是777的) |
| … | … | … |
### tar
用來打包與解包的指令。
> 之所以不說是壓縮以及解壓縮是因為 `tar` 真的只會打包跟解包,並不會壓縮檔案
https://www.readfog.com/a/1647231450265784320
```bash=
tar {A|c|d|r|t|u|x}[OPTIONS] [ARGS]
```
首先是常用的幾個參數,這些參數用來表示接下來你希望 `tar` 做甚麼操作,這幾個參數會是獨立使用的
| args | 意義 |
| ---- | ---- |
| `-c`, `--create` | create, 建立 |
| `-x`, `--extract` | extract, 解包 |
| `-t`, `--list` | list, 查看詳細內容 |
| `-r`, `--append` | append, 在壓縮檔尾端再追加文件 |
接下來是關於檔案屬性的可選參數,決定好處理的檔案型態
| args | 意義 |
| ---- | ---- |
| `-z`, `--gzip` | 使用 `gzip` 處理,用於包含 `.gz` 屬性檔案 |
| `-j`, `--bzip2` | 使用 `bzip2` 處理,用於包含 `.bz` 屬性檔案 |
| `-J`, `--xz` | 使用 `xz` 處理,用於包含 `.xz` 屬性檔案 |
| `-Z`, `--compress` | 使用 `compress` 處理,用於包含 `.Z` 屬性檔案 |
| `-a`, `--auto-compress` | 自動選擇合適的 compressor |
其他常用可選參數
| args | 意義 |
| ---- | ---- |
| `-v`, `--verbose` | 顯示所有過程 |
| `-O`, `--to-stdout` | 將檔案輸出到 stdout |
最後, `-f` 是必要參數,用於指定檔案的名稱,並且必定要是最後一個參數
> 好用的網站 http://note.drx.tw/2008/04/command.html
### du
> Estimate file space usage
```bash=
du [選項] [檔案]
```
用來計算使用空間大小的工具,可以加上參數 `-h` 將 bytes 單位轉換成比較合適的單位來看。
通常也會使用 `--max-depth=` 來指定遞迴深度。
```bash=
du -h --max-depth=0
```
如此一來就可以拿到當前目錄的空間大小
### scp
> OpenSSH secure file copy
透過 ssh protocal 在兩個裝置上傳輸資料
> https://blog.gtwang.org/linux/linux-scp-command-tutorial-examples/
```bash=
scp [帳號@來源主機]:來源檔案 [帳號@目的主機]:目的檔案
```
如果要傳送的是資料夾,需要加上參數 `-r` 表示 recursively。
### rsync
> a fast, versatile, remote (and local) file-copying tool
跟 cp, scp 類似,不過可以用更加有效率的方式傳輸資料。
> https://blog.gtwang.org/linux/rsync-local-remote-file-synchronization-commands/
```bash=
rsync [參數] [來源檔案] [目的檔案]
```
通常會加上參數 `-a` 遞迴備份所有子目錄底下的資料夾以及檔案,並且保留時間戳記等資訊。
如果要傳輸的是資料夾,同樣加上參數 `-r` 表示 recursively。
## Linux File Hierachy
`/bin` 用於存放重要的標準執行檔(**binary**),包含 `ls`, `cp`, `cat` 等等檔案。
`/dev` 用於存放任何裝置(**device**)的檔案,包含驅動程式、Terminal、各種 port。
`/etc` 用於存放系統配置的檔案
`/home` 家目錄
`/lib` 存放各種 **library** 的目錄
`/mnt` 掛載系統時會出現在這邊
`/opt` 存放各種 **optional** 的執行檔
## Linux I/O
> https://blog.gtwang.org/linux/linux-io-input-output-redirection-operators/
在 Linux 當中輸入輸出被分成三類
- stdin (0)
- stdout (1)
- stderr (2)
可以透過重導向符號將輸入輸出流重新導向
- `>` 可以將 stdout 導向到檔案
更普遍的來說,語法會是 `N>` ,當中的 N 就是想要重新導向的 IO 代碼,預設為 1 也就是 stdout
可以透過 `2>&1` 將 stderr 導向到 stdout
- `>>` 和 `>` 類似,不過會是 append,不會複寫到原先的內容
- `<` 可以將檔案內容導向到 stdin 當中
## Other Command
### 其他常用連接符
- `|`
念作 pipe,也如同字面上的意義可以串連 I/O stream,將輸出變成另一者的輸入。
例如 `ls | nl` 就會將 `ls` 的 stdout 當成 `nl` 的 stdin
- `&`
將程式移動到背景執行。
例如 `sleep 10&`,接下來可以透過 `ps` 來查看目前正在執行的程式,就會發現 `sleep` 確實存在。
<center>
<img src=https://i.imgur.com/eHUKZLj.png height=300>
</center>
> 值得一提的是,這邊顯示的 `TIME` 是指 CPU time,因此如果有多個 CPU,時間是會疊加上去的。
- `&&`
連接多個指令,不過只有在左側的指令***執行成功***才會繼續執行右側的指令
- `||`
連接多個指令,不過只有在左側的指令***執行失敗***才會繼續執行右側的指令
### ln
> make links between files
建立連結檔案,類似於建立捷徑
> https://blog.gtwang.org/linux/linux-ln-command-tutorial-examples/
連結分成***硬連結***以及***軟連結***
硬連結產生的檔案會與連結檔案有相同的***inode***,而軟連結則會有自己的***inode***
:::success
那麼什麼是 ***inode*** 呢?
> https://www.796t.com/content/1542281710.html
inode 是 index node 的簡稱,是 Linux 系統用來尋找實際資料的結構,當中記錄了包含
- 檔案大小
- 擁有者
- 所屬 Group
- 檔案權限
- timestamp
- link numbers
- block 位置
可以透過 `stat` 指令查看檔案的 inode 資訊,這些資訊又被稱為 metadata(元資訊)

硬碟基本上會被分成兩個區塊,分別是***資料區***以及***inode table***,分別存放檔案內容以及 inode 資訊。
可以透過 `df` 指令檢視每個硬碟分割出來的 inode 總數以及可以使用的數量
每個檔案都會有一個 inode number,作業系統會用這個號碼來辨識不同檔案。
當我們要存取檔案的時候,實際上會經過三個步驟
1. 找到檔案相對應的 inode number
2. 透過 inode table 找到對應的 inode metadata
3. 藉著 metadata 找到檔案所在的 block,接著存取
無論是單純的檔案或是目錄,都會有一個相對應的 inode number
在 `ls` 加上參數 `-i` 可以再看到檔案以及目錄的 inode number

> 可以觀察到這一層的`..`跟上一層的`.` inode number 是一樣的!
:::
理解了 inode 是甚麼之後,接下來大致上就能夠理解**硬連結**以及**軟連結**是甚麼了。
硬連結會跟連結檔案有同一個 inode number,因此如果有兩個檔案 A, B,他們有相同的 inode number,如果刪除了 A,對 B 也不會有影響,仍然能夠順利存取。
不過軟連結就會相反,如果有兩個檔案 A, B,B 是 A 的軟連結,那麼當 A 被刪除的時候,因為 B 需要透過 A 才能存取到檔案,所以就會存取失敗。
***建立硬連結***
```bash
ln [原始檔案] [目標檔案]
```
***建立軟連結***
```bash
ln -s [原始檔案] [目標檔案]
```
#### 有趣的應用
因為檔案存取都會需要先透過 inode,所以如果要刪除檔案的話也可以透過 inode 刪除!
首先,`find` 指令可以加上參數 `-inum` 去找到指定 inode number 的檔案
如果是單純的檔案,`find` 指令可以再加上 `-delete` 刪除找到的檔案
如果是目錄的話,則要使用 `-exec rm -i {} \;` 刪除。
> 這種刪除方式通常應用在檔案名稱包含奇怪的字元的時候,直接輸入名稱或是在 command line 輸入會出問題的時候就很好用
### which
> locate a command
```bash=
which [指令]
```
用來找到一個指令的檔案位置
### ip
> show / manipulate routing, network devices, interfaces and tunnels
用來查看和管理網路相關的好用指令。
大致上的指令結構是
```bash=
ip [ OPTIONS ] OBJECT { COMMAND | help }
```
實際上 `ip` 的 help 裡面寫得很清楚

如果想要知道每個 OBJECT 分別要怎麼使用,最快的方法就是
```bash
ip [OBJECT] help
```
### alias
類似於 C++ 當中的 define,可以用某個關鍵字來替代特定字串
- 讀取:`alias`
- 新增:`alias KEY=VALUE`
- 刪除:`unalias KEY`
不過 alias 並不會永久保留,如果希望下次仍然保有這樣的設定的話可以修改 `~/.bashrc`, `~/.bash_profile`, `~/.bash_aliases` 其中之一,建議放在 `~/.bash_aliases` 比較方便管理。
## Package Manager
在 Linux 當中如果要下載、安裝、更新 package 的話會需要透過 package manager 來操作,不同的 OS 會用不同的 package manager。
| OS | Package Manager |
| ------ | --------------- |
| ubuntu | apt |
| Arch | pacman |
| CentOS | yum |
| maxOS | homebrew |
| NachOS | MP5 |
## Ubuntu: apt
***更新***
```bash=
apt update
```
***下載***
```bash=
apt install <package>
```
> 如果希望下載特定版本的 package 可以加上 `=<version>`
```bash=
apt install <package>=<version>
```
***升級***
```bash=
apt upgrade
```
:::success
`update` 跟 `upgrade` 是有差異的
在更新 package 的時候會需要經過兩個階段
1. 更新 package 版本資訊
2. 根據版本資訊找出需要更新的版本並更新
因此 `update` 僅是更新 metadata 下來,但是實際上要更新到 package 需要再執行 `upgrade`,通常我們會直接下
```bash=
apt update && apt upgrade
```
:::
***移除***
```bash=
apt remove <package>
```
***查看版本***
```bash=
apt-cache policy <package>
```
## Arch: pacman
> https://itsfoss.com/pacman-command/
***下載***
```bash=
pacman -S <package>
```
***移除***
```bash=
pacman -R <package>
```
***更新並升級***
```bash=
pacman -Syu
```
> `-S` 表示 sync
> `-y` 表示 refresh local cache
> `-u` 表示 system update
## CentOS: yum
***下載***
```bash=
yum install <package>
```
***移除***
```bash=
yum remove <package>
```
***更新***
```bash=
yum update
```
> yum 的 `update` 似乎就能夠直接更新了,而 `upgrade` 則會連同過舊的 package 一起更新,比較會用在版本升級
***列清單***
```bash=
yum list
```
---
不過在像是國網的電腦上通常不會有 sudo 的權限,會導致有許多的 package 沒辦法好好下載下來。
可以試著看看 [spack](https://spack.io) 這個 package manager
## Process
在 OS 上面執行的每一個工作都會是一個 process,就如同 windows 當中的工作管理員,在其中看到的每個項目都是 process。
那麼,該如何管理 Linux 當中的 process 就是接下來要探討的議題。
### ps
> report a snapshot of the current processes. Process Status
`ps` 這個指令能夠讓我們查看當前的 process。在不佳上任何的參數時顯示的會是 user 在登入時的資訊。
常用的參數有 `-l` 以及 `-aux`,分別是**顯示 long format**以及**顯示所有的 process**。
> 也可以用 `pstree` 看到 process 之間的層級關係
### kill
> Send a signal to a job.
> https://blog.gtwang.org/linux/linux-kill-killall-xkill/
`kill` 可以將 process 移除,使用方式為
```bash=
kill <PID>
```
不過有時候如果程式當掉沒辦法透過上面的方法停止,可以嘗試送不同的訊號進去
```bash=
kill -9 <PID>
```
如此就能夠直接強制停止。`kill` 常用的指令有幾個:
- `-2`:等同於 Ctrl+C
- `-9`:強制停止
- `-15`:以正常的程序通知程式要停止,是預設的訊號
- `-l`:列出所有可用的訊號
實際上,當程式在執行的過程當中如果我們按下 Ctrl+C 或是 Ctrl+Z 也是會送一個 signal 給那個 process。
- `Ctrl+C` 會傳送 `SIGINT(2)` 給 process,正常情況下會使程式停止。
- `Ctrl+Z` 會傳送 `SIGTSTP(20)` 給 process,讓 process 暫時停止並移動到背景
如果想要繼續執行剛剛暫停的 process,可以輸入指令 `fg`,他會傳送 `SIGCONT(18)` 給 process。
> `INT` 是 Interrupt 的意思
:::info
到這邊需要釐清的是,`kill` 雖然叫做 kill,不過他本質上做的事情就是傳送 signal 給 process,並不是每次都會是傳送 kill 的 signal。
:::
### top & htop
> https://medium.com/starbugs/do-you-understand-htop-ffb72b3d5629
不過 `ps` 格式是真的偏難看,可以考慮使用 `top` 會更清楚好用,並且每 3 秒更新一次,能夠看到即時的狀況。
此外,`htop` 是 `top` 更棒的版本,所以會更推薦使用 `htop`。

- ***CPU***

在 `htop` 的畫面當中上面的每個數字表示的是每個 CPU 現在在執行的 process,不同的顏色表示不同的 priority
- 紅色:kernal thread,最重要、 priority 最高的 process
- 綠色:normal priority thread,一般的 priority
- 藍色:low priority thread,比較無關緊要的 process
這邊的 CPU 數量指的是執行緒的數量。
- ***Memory & Swap***

Memory 表示記憶體用量,同樣會有不同的顏色顯示
- 綠色:被 process 占用的記憶體
- 藍色:buffer pages,用來儲存 metadata,短時間內重複執行某些指令就可以直接透過 buffer 獲取,不經過硬碟
- 橘色:cache pages,與藍色類似,不過儲存的是檔案內容而非 metadata
而 Swap 則是當 Memory 不太夠用的時候,系統就會將記憶體上的部份東西 swap 到硬碟上
- ***Load Average***

`163, 2530 thr; 2 running` 表示的是
1. 總共有 `163` 個 process
2. 總共有 `2530` 個 thread
3. 其中 `2` 個 thread 正在執行
`0.36 0.39 0.64` 表示的是最近**1 分鐘**、**5 分鐘**、**15 分鐘**內平均有多少個 thread 需要 CPU
而 `Uptime` 就是開啟的時間長度。
- ***PID & USER***

紀錄每個 process 的 PID 以及執行的 user
- ***PRI & NI***

是 **Priority** 以及 **Nice** 的簡稱,兩者都是優先度的指標,優先度的數值越低優先度越高。
其中,**Priority** 是由系統自行設定的優先度,而 **Nice** 則是由使用者自行設定的,不過系統不見得會參考 Nice 的指標。
- ***VIRT & RES & SHA***

是 **Virtual Memory**, **Resident** 以及 **Shared Memory** 的簡稱。
- **Virtual Memory** 表示 process 能夠存取到的 memory 總和
- **Resident** 表示實際上占用的 memory 大小
- **Shared Memory** 表示能夠分享給其他 process 的記憶體大小
- ***S***

是 **State** 的簡稱,常見的有...
- `R`:Running,正在執行或是正在 running queue 當中等待 CPU 排程
- `S`:Sleep,正在睡覺,有事做才會起來
- `D`:也是在睡覺,不過等待的必定是 I/O
- ***CPU% & MEM%***

- **CPU%**:這段時間內平均用了多少 CPU
- **MEM%**:這段時間內平均用了多少 MEM,用 RES 計算
- ***TIME+***

總共占用多少 CPU time。
---
## Tmux
> - https://larrylu.blog/tmux-33a24e595fbc
> - https://gist.github.com/MohamedAlaa/2961058
一種 Terminal Multiplexer,當你希望同時使用多個 Terminal 或是想執行多個 process 的時候一個好用的工具。
執行 `tmux` 之後會看到畫面底下出現綠色的狀態列。

- ***Session***
每次下 `tmux` 就會產生一個新的 session,左下角 `[]` 內的數字就表示當前這個畫面是哪一個 session。
- ***Window***
每個 session 當中可以有很多個 window,你能夠看到的整個畫面都會被稱為一個 window。左下角在 `[]` 之後的數字就表示當前是哪一個 window。
- ***pane***
一個 window 可以切割成多個區塊,每個區塊就是一個 pane。
### pane
- `<Ctrl + B> + "`:水平分割
- `<Ctrl + B> + %`:垂直分割
- `<Ctrl + B> + <方向鍵>`:移動到其他 pane
- `<Ctrl + B> + space`:切換布局
- `<Ctrl + B> + X`:關閉目前的 pane
- `<Ctrl + B> + <ctrl + 方向鍵>`:調整 pane 大小
### session
- `<Ctrl + B> + D`:將當前的 session 放到背景當中
- `tmux at`:attach 到背景的 session
- `<Ctrl + B> + <kill-session>:`:刪除當前 session
- `<Ctrl + B> + $`:重新命名 session
- `<Ctrl + B> + S`:以視覺化清單切換 session
- `<Ctrl + B> + L`:切換到上一個使用的 session
- `<Ctrl + B> + (`:切換到上一個 session
- `<Ctrl + B> + )`:切換到下一個 session
### Window
- `<Ctrl + B> + C`:建立新的 window
- `<Ctrl + B> + W`:以視覺化清單切換 window
- `<Ctrl + B> + N`:切換到下一個 window
- `<Ctrl + B> + P`:切換到上一個 window
- `<Ctrl + B> + <數字>`:切換到指定 window
- `<Ctrl + B> + &`:關閉目前的 window
## Cluster System
沒有過多的介紹,但可以參考台灣杉三號的說明
> https://man.twcc.ai/@TWCC-III-manual/H1bEXeGcu
###### tags: `超算筆記`