Skip to content

antony@notes:~/misc$ cat "Process.md"

Process

2022-08-07· misc ·Linux

Process

[TOC]

Docker,這家公司的技術是2021年的電腦基礎概論(全球),它推出了一個技術叫做"Container(貨櫃)"。

  • “Container” 是一台電腦,這個技術主要威脅到VM(virtual machine)虛擬技術,Container也是虛擬技術做出來的電腦,但它比VM輕量許多,且速度又快。
  • 實體電腦一台可以做出很多很多的Container,管裡維運這堆Container的技術就是"Kubernetes"。

Kubernetes,這套系統是用來管理維運Docker,2021年的電腦基礎概論(全球),由goolge公司設計。

提問:為何Kubernetes要管理那麼多台container,目的是甚麼? 因為可以用Kubernetes做出Hadoop,這是企業會實質會用到的系統。 Hadoop,大數據平台,做資料分析平的。

Spark,幫公司做出決策,做深度分析的,也就是 “machine learning” 機器學習,用的語言是python。


落第雲系統架構


Alpine Linux 作業系統

因為系統很小,所以執行效能一定高資安等級相當的高,小到沒法破壞。

Linux 是由幾百萬行的程式碼組成的,主要的精神是可以 “客製化” 作業系統

  • lib=library=程式庫(儲存別人寫好的程式、套件)
  • busybox 容量只有800多K,卻可以模擬出很多 Linux 的指令, e.g. ping,rm,mv,ifconfig,ls
    • busybox ls -alh ,其中 -h 為 human-readable ,把容量的部分轉成人類易讀的 (KB,MB等)
    • 一般來說,alpine 的指令都會指向 /bin/busybox (除非有改過),例如 /bin/cat 則會到 -> /bin/busybox

老師有自己換裝過,所以像是cat這個命令,在老師的環境裡,會指向/bin/coreutils,換裝個原因是因為busybox屬於簡易版的,因為要模擬出很多個命令,所以沒辦法做到非常專業,所以老師才會換裝到標準套件。 busybox可以模擬出很多linux的命令,可以打ls -al /bin | grep cat,就會看到那個命令後面有一個箭頭指向/bin/busybox

  • sudo apk update (apk = alpine package)更新最新的套件清單,sudo apk upgrade 將以安裝的套件去對照清單,然後更新,sudo apk add tree,可以強化alpine 的作業系統功能,少了那些功能就可以用add把它加進去
  • 如果需要圖形介面可以使用 XWindow 其他 Linux 發行版也是用這個* sudo apk update 更新最新的套件清單,sudo apk upgrade 將以安裝的套件去對照清單,然後更新
  • alpine 這種輕量化的 OS 已經是未來趨勢,因為它的資安等級很高。

Alpine Linux 是一套由社群開發,以安全為導向的 Linux 作業系統,目前最新的版本 v3.13.4 在 2021-03-31 發布。 跟一般的 Linux 發行版不一樣的地方是 Alpine 是使用 musl libc 和 busybox 來減少系統需求容量(5 MB )和執行消耗資源。 比起其他輕量化 Image (如:Busybox,Image 大小為1.113MB), Alpine 的優勢在於多了像是 apt 之於 Ubuntu 這樣的套件管理工具 apk ,官方提供了大量的套件供開發者使用,可以透過網站或者直接下 apk 指令進行查詢或者安裝。

  • Alpine 的 busybox 是 HardLink, 而不是 Softlink. Docker busybox image 沒有提供 套件安裝平台

補充: musl libc musl,一種C標準函式庫,主要使用於以Linux核心為主的作業系統上,目標為嵌入式系統與行動裝置,採用MIT授權條款釋出。作者為瑞奇·費爾克(Rich Felker)。開發此庫的目的是寫一份乾淨、高效、符合標準的C標準庫。 Musl是從零開始設計的。一是希望讓靜態連結更高效;二是現有的C標準庫在一些極端條件下表現很糟糕,競態條件、資源不足時常常會出問題,而Musl試圖避免它們來達到較高的即時魯棒性。

Busybox BusyBox是一個遵循 GPL協定、以自由軟體形式發行的應用程式。Busybox在單一的可執行檔中提供了精簡的Unix工具集,可執行於多款 POSIX 環境的作業系統,例如 Linux(包括Android)、Hurd、FreeBSD 等等。由於BusyBox執行檔的檔案比較小,使得它非常適合使用於嵌入式系統。作者將BusyBox稱為「嵌入式Linux的瑞士軍刀」。


終端機的功能是甚麼? 終端機內執行的程式只為shell(貝殼程式),提供input、output給主機,本身有螢幕(顯示結果)及鍵盤(輸入指令),並無硬碟。

Linux 一開始就提供了多工的介面,達到協同作業,連接很多終端機 bash script 也是一種程式語言,熟bash script 月薪五萬以上!!


computer program

program 是一個檔案,要有執行權限才能執行,而程式的執行有兩種方式 :

  1. interpreter(直譯式) ,把命令一行一行的執行下去 影像

  2. compiler(編譯式), 是把人類看得懂的程式轉成電腦看得的(011010 bin 檔) machine code 再執行

compiler和interpreter都會轉換成machine code,只是interpreter是一行一行的轉

shell script 的 interpreter 是由開頭的 #! 來指定(與python類似) ,如果是 bash script 就會指定 #!/bin/bash 來翻譯

什麼是computer program?

指令的集合aka程式,通常由程式設計師以某種程式設計語言編寫,指示電腦或其他具有訊息處理能力裝置每一步動作的指令,在系統中以 program=檔案的形式存在,其中包含數個指令,可以由電腦去依照指令執行特定動作,語言轉換方式分為compiler及interpreter。


開發 Golang 網站

Golang語言,有C語言的速度python的簡潔Java的物件 Docker和Kubernetes都是用Golang這個語言寫出來的 內建支援多國語言

範例:

$ cd; mkdir mygo; cd mygo
$ echo 'package main
import (
	"fmt"
	"log"
	"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {    ##開頭的func是function的意思
	fmt.Fprintln(w, "Hello, 世界")
}
func main() {
	http.HandleFunc("/", handler)
	log.Fatal(http.ListenAndServe(":8888", nil))
}' > main.go

$ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a main.go  
## go build是compiler,他會把我們寫的看得懂的program(main.go)編譯成下行(main)我們看不懂的執行程式,也是個porgram

$ ./main

證明main.go是剛剛寫的program ⬇️ ,這個程式的功能主要是,啟動之後是個網站,到他的首頁後會出現"Hello, 世界",還有做一個設定是port:8888

bigred@m1:~/mygo$ cat main.go
package main
import (
"fmt"                                         ## 這是一個library
"log"                                         ## 這是一個library
"net/http"                                    ## 這是一個library
)                                             ## import這個命令就是等下我的程式(下面的program)要使用"fmt"、"log"和"net/http"這三個library
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, 世界")
}
func main() {                                 ## main()是開始的程式,一開始成形的地方
http.HandleFunc("/", handler)                 ## 在go語言要啟動一個web server,就打一個"http."說網站的根("/")裡面要交給一個小程式handler
log.Fatal(http.ListenAndServe(":8888", nil))  ## 連接網路到一個IP位置去,除了IP位置以外,還要標示port number :8888

來看編譯後的執行檔,也是個program ⬇️

bigred@m1:~/mygo$ head -c 10 main ## 看main這個檔案前10個byte的資料
ELFbigred@m1:~/mygo$              ## bigred前面的ELF就是所謂的機械碼,因為很多碼在螢幕上是出現不了的,所以才顯示這樣

執行完"./main"後,再開一個CMD,連進m1,下指令 curl http://localhost:8888 也可以直接在windows系統裡面直接curl curl http://192.168.61.4:8888

練習

把"hello,世界"改成"imok"

第一步 nano main.go 把裡面的"hello,世界"改成"imok" Ctrl O 儲存,Ctrl X 離開

第二步 再執行一次go buid這個compiler bigred@m1:~/mygo$ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a main.go 執行完compiler後, 再執行./main

最後 到新的CMD裡下curl http://192.168.61.4:8888

成功!以上就是compiler的程式設計.


Java Program

JAva語言製作跟執行的過成:

影像

寫一個Java的program,這個原始程式是我們看得懂的,經過一個編譯器compiler,翻譯出來的叫做"byte code(位元碼)",這個產生出來的byte code是人沒辦法直接閱讀的,是要丟給另一個程式Java virtual machine(JVM)讀的,JVM也是一個program,這個program會把剛剛產生的byte code讀進來,他來幫你翻譯成真正電腦看得懂的machine code,然後再去執行他

註: 在windows作業系統裡面,要事先安裝JVM這個程式;在Linux作業系統裡面,也要安裝專屬於Linux的JVM程式;Mac OS作業系統裡面,也可以安裝專屬於Linux的JVM程式,由上圖可知,不同的作業系統,通通都有對應的JVM程式

提問:為何會有這種架構? 答: 我們寫Java程式,翻譯成byte code(它的副檔名是.class),我們只要把這個動作做完,這個編譯過後的程式碼,就可以分別到Windows、Linux和Mac OS裡面跑,這就是Java厲害的地方,程式寫完,編譯一次,就可以在所有的作業系統裡面來做執行,Java它跨平台

Java是interpreter and compiler 的混合語言 前面編譯的過程是compiler,後面透過JVM的過程是interpreter(第一代的JVM呆呆地,把byte code一行一行慢慢讀,再轉換成machine code,這個過程就是interpreter,可是之後的JVM會把一批的byte code直接換成機械碼,內部自己做一個compiler的動作,就不是一行一行的)


撰寫與執行 Java 程式

第一步 先撰寫一個Java程式

bigred@m1:~$ echo $'public class ReverNum {
>   public static void main(String[] args) {
>
>     int num = 1234, reversed = 0;
>     while(num != 0) {
>       int digit = num % 10;
>       reversed = reversed * 10 + digit;
>       num /= 10;
>     }
>
>     System.out.println("Reversed Number: " + reversed);
>   }
> }'> ReverNum.java

第二步 用Javac去編譯剛剛的程式

bigred@m1:~$ javac ReverNum.java
-bash: javac: command not found

發現錯誤提示:command not found後,用ls -al查看

bigred@m1:~$ ls -al /usr/lib/jvm/java-1.8-openjdk/bin/javac
-rwxr-xr-x 1 root root 14384 Oct 14 23:21 /usr/lib/jvm/java-1.8-openjdk/bin/javac

原因是因為javac這個命令不再環境變數裡面,看環境變數

bigred@m1:~$ echo $PATH
/home/bigred/bin:/home/bigred/dt/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

發現原本的環境變數裡面沒有/usr/lib/jvm/java-1.8-openjdk/bin/javac,用export加入環境變數

bigred@m1:~$ export PATH=/usr/lib/jvm/java-1.8-openjdk/bin/:$PATH
bigred@m1:~$ echo $PATH
/usr/lib/jvm/java-1.8-openjdk/bin/:/home/bigred/bin:/home/bigred/dt/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

再試一次用javac編譯一次

bigred@m1:~$ javac ReverNum.java
bigred@m1:~$ dir ReverNum.*
-rw-r--r-- 1 bigred bigred 714 Feb 22 17:15 ReverNum.class
-rw-r--r-- 1 bigred bigred 278 Feb 22 16:06 ReverNum.java

可以看到ReverNum.class,副檔名是.class代表成功編譯,可以下head再檢查

bigred@m1:~$ head -c 10 ReverNum.class
4,bigred@m1:~$

結果顯示"4,",意思不是只有這樣,而是因為螢幕顯示不出來,編譯完的叫做byte code,它是給JVM讀的,注意JVM跟VM是完全不一樣的東西,JVM雖然是virtual machine,但跟VMWare做的VM的內部結構完全不同

最後用java(JVM)來執行這個程式,可以把 java 這個指令就當作是 JVM (讀取.class 檔案的 bytecode 並執行)

bigred@m1:~$ chmod +x ReverNum.class
bigred@m1:~$ java ReverNum
Reversed Number: 4321

這邊老師已經有先幫我們在Alpine上面下sudo apk add openjdk8這個命令,也就是說先下載了openjdk8這個壓縮檔,只要解壓縮後,就可以看到java(JVM)

Python

Is Python interpreted or compiled ?

認識Process

  • program 程式
    • run 程式的必要條件:
      1. 使用者有權限
      2. 程式具有可執行的權限
  • process 程序
  • thread 執行序

Process (程序) 運作架構圖 我們的的電腦裡面會放很多的process,這些process是由我們寫的program來的,process在記憶體裡面跑,一定有3個東西:

  1. 程式碼,電腦能夠讀的machine code
  2. 執行它的使用者基本資訊,而基本資訊裡有user id (使用者的代號,UID)…等
  3. 程序在跑,一定會有一個執行的代號,也就是PID

顯示程序(Process)資訊

條列式顯示所有程序 :

bigred@m1:~$ ps -eo user,pid,cmd,%mem,%cpu | head -n 5
USER        PID CMD                         %MEM %CPU
root          1 /sbin/init                   0.0  0.0
root          2 [kthreadd]                   0.0  0.0
root          3 [rcu_gp]                     0.0  0.0
root          4 [rcu_par_gp]                 0.0  0.0

這裡的 -e 參數是代表輸出所有程序的資訊,而 -o 參數則是用來指定輸出欄位用的,後面接著所有想要輸出的欄位名稱,這裡我們讓 ps 輸出以下幾個欄位: pid:程序 ID(process ID)。 cmd:程式名稱。 %mem:記憶體使用量(百分比)。 %cpu:CPU 使用量(百分比)。 [註] 在 Alpine Linux 系統中 , 內定 ps 命令是由 busybox 執行, 如要執行全功能 ps 命令, 請執行 sudo apk add procps


依照 CPU 使用量,從大到小排序程序

bigred@m1:~$ timeout 60s yes >/dev/null &           ## 讓yes這個程式60秒,再把一堆Y丟到黑洞,並且&的意思是
把程式推到背景去執行,因為如果不推到背景去執行,終端機會沒辦法作業
[1] 67706
bigred@m1:~$ ps -eo user,pid,cmd,%mem,%cpu --sort=-%cpu | head -n 3
USER        PID CMD                         %MEM %CPU
bigred    67707 yes                          0.0 98.3
root       4135 kube-apiserver --advertise-  3.5  4.3

可以看到執行YES這個program的使用者是bigred,這時候會變成process,而它的的PID(執行代號)是67707,記憶體使用量是0%,CPU的使用量是98.3%

YES這個命令的應用是給cisco工程師使用的,他們在設定網路設備的時候會需要一直按YES,這時候就會需要這個指令

如何證明YES是一個檔案?

bigred@m1:~$ which yes
/usr/bin/yes
bigred@m1:~$ ls -al /usr/bin/yes
lrwxrwxrwx 1 root root 9 Nov 27 20:47 /usr/bin/yes -> coreutils

安裝完整功能的pstree

bigred@m1:~$ sudo apk add pstree
fetch http://dl-cdn.alpinelinux.org/alpine/latest-stable/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/latest-stable/community/x86_64/APKINDEX.tar.gz
(1/1) Installing pstree (2.39-r1)
Executing busybox-1.34.1-r4.trigger
OK: 1692 MiB in 294 packages

以樹狀顯示Alpine Linux 程序資訊

bigred@m1:~$ pstree -g 3
─┬= 00001 root /sbin/init
 ├──= 03856 root /sbin/getty 38400 tty6
 ├──= 03852 root /sbin/getty 38400 tty5
 ├──= 03847 root /sbin/getty 38400 tty4
 ├──= 03843 root /sbin/getty 38400 tty3
 ├──= 03839 root /sbin/getty 38400 tty2
 ├─┬= 03837 root /bin/login -f bigred
 │ └─┬= 03848 bigred -bash
 │   └─── 03913 bigred dialog --title  Cloud Native Trainer  --textbox /tmp/sinfo 24 85
...以下省略
  • /sbin/init 是第一個啟動的程式,他的pid就是00001,由root做執行

    • 提問: 誰啟動/sbin/init這個程式? Linux 的 kernel會幫我們啟動整個Linux系統裡面的第一個process
  • tty1(第一個終端機)在執行login(03837 root /bin/login -f bigred),也就是登入的工作,接著

  • 03848 bigred -bash貝殼程式啟動,接著

  • 3913 bigred dialog --title Cloud Native Trainer --textbox /tmp/sinfo 24 85啟動

    在老師的機器裡面,老師有設定login的檔案,讓它可以自動登入bigred

  • 注意!在帳號密碼打完,shell程式啟動以後,第一個跑的程式其實是/etc/profile

bigred@m1:~$ tail -n 10 /etc/profile
alias kd='kubectl delete'
alias kc='kubectl create'
alias ks='kubectl get pods -n kube-system'

[ -f /home/bigred/dt/alpine.bash ] && source /home/bigred/dt/alpine.bash

# /etc/local.d/rc.local.start (相當於 rc.local) create /tmp/sinfo
if [ -z "$SSH_TTY" ]; then
   [ -f /tmp/sinfo ] && dialog --title " Cloud Native Trainer " --textbox /tmp/sinfo 24 85; clear
fi

可以看到倒數第二行的" Cloud Native Trainer “,由此可知dialog是由/etc/profile這個program執行的,所以在alpine linux系統裡面,有很多使用者他們需要的變數或功能,老師都會把它寫在這個程式裡面。 /etc/profile就是bash script,只要帳號密碼一打成功,他就是第一個被執行的bash script程式,完了以後,它才會在跑道使用者的家目錄裡面,去執行.bashrc這個程式,一樣也是bash script程式


 bigred@m1:~$ pstree -g 3
 ...以上省略
 ├─┬─ 04039 root sshd: /usr/sbin/sshd [listener] 0 of 10-100 startups
 │ └─┬= 04256 root sshd: bigred [priv]
 │   └─┬─ 04262 bigred sshd: bigred@pts/0
 │     └─┬= 04264 bigred -bash
 │       └──= 88243 bigred pstree -g 3
...以下省略

我們在windows的CMD上面打,ssh bigred@192.168.61.4就是跟 04039 root sshd: ...省略這個openssh server做連接,

連接到以後,04256 root sshd: bigred [priv]會偵測到是bigred要登入進來

之後,04262 bigred sshd: bigred@pts/0會給一個遠端的虛擬終端機(pts)給bigred這個帳號使用,

進去終端機後,一樣會跑04264 bigred -bash這個貝殼程式

只要是linux系統的終端機,進去以後一定跑貝殼程式

只要我們的帳號有登入成功,在Alpine Linux的系統裡面,不管是在本機的終端機(tty)還是遠端虛擬的專端機(pts),進去以後一定都會去執行/etc/profile,某些公司裡特殊的shell例外

注意:要切換使用者還是重開一個CMD登入好,su切換使用者,環境變數跟資料會有缺失

2021/09/24 下午2:39繼續

tags: Linux