第四周-雲端計算運維作業

TestAL4193發表於2024-05-04

1. 使用while read line和/etc/passwd,計算使用者id總和。

	  sum=0
	  while read line
	  do
	   echo " $line" &>/dev/null
	   ((sum++))


	  done </etc/passwd
	  echo "$sum"

2. 總結索引陣列和關聯陣列,字串處理,高階變數使用及示例。

陣列定義:
emp[0]=zz
emp[1]=zz1
emp[2]=zz2
title=("e" e1 e2)
num=({1..10})

關聯陣列(自定義陣列)
declare -A 陣列 使用關聯陣列需要先定義
emp[frist]=l1
emp[second]=l2

基於偏移量取字串

返回字串變數var的字元的長度,一個漢字算一個字元
${#var} 
返回字串變數var中從第offset個字元後(不包括第offset個字元)的字元開始,到最後的部分,
offset的取值在0 到 ${#var}-1 之間(bash4.2後,允許為負值)
${var:offset} 
返回字串變數var中從第offset個字元後(不包括第offset個字元)的字元開始,長度為number的部分
${var:offset:number}
取字串的最右側幾個字元,取字串的最右側幾個字元, 注意:冒號後必須有一空白字元
${var: -length}
從最左側跳過offset字元,一直向右取到距離最右側lengh個字元之前的內容,即:掐頭去尾
${var:offset:-length}
先從最右側向左取到length個字元開始,再向右取到距離最右側offset個字元之間的內容,注意:-length
前空格,並且length必須大於offset
${var: -length:-offset}

基於模式取子串

 其中word可以是指定的任意字元,自左而右,查詢var變數所儲存的字串中,第一次出現的word, 刪除字
符串開頭至第一次出現word字串(含)之間的所有字元,即懶惰模式,以第一個word為界刪左留右
${var#*word}
從var變數的值中刪除以word開頭的部分
${var#word}
同上,貪婪模式,不同的是,刪除的是字串開頭至最後一次由word指定的字元之間的所有內容,即貪婪模
式,以最後一個word為界刪左留右
${var##*word}
${var##word}
##################################################################################
其中word可以是指定的任意字元,功能:自右而左,查詢var變數所儲存的字串中,第一次出現的word, 
刪除字串最後一個字元向左至第一次出現word字串(含)之間的所有字元,即懶惰模式,以從右向左的第一
個word為界刪右留左
${var%word*}
${var%word}
同上,只不過刪除字串最右側的字元向左至最後一次出現word字元之間的所有字元,即貪婪模式,以從右向
左的最後一個word為界刪右留左
${var%%word*}
${var%%word}

高階變數
高階變數賦值:
image

高階變數用法-有型別變數

  • Shell變數一般是無型別的,但是bash Shell提供了declare和typeset兩個命令用於指定變數的型別,兩個命令是等價的

  • declare [選項] 變數名
    -r 宣告或顯示只讀變數
    -i 將變數定義為整型數
    -a 將變數定義為陣列
    -A 將變數定義為關聯陣列
    -f 顯示已定義的所有函式名及其內容
    -F 僅顯示已定義的所有函式名
    -x 宣告或顯示環境變數和函式
    -l 宣告變數為小寫字母 declare –l var=UPPER
    -u 宣告變數為大寫字母 declare –u var=lower

    返回字串變數var的字元的長度,一個漢字算一個字元
    ${#var}
    返回字串變數var中從第offset個字元後(不包括第offset個字元)的字元開始,到最後的部分,
    offset的取值在0 到 ${#var}-1 之間(bash4.2後,允許為負值)
    ${var:offset}
    返回字串變數var中從第offset個字元後(不包括第offset個字元)的字元開始,長度為number的部分
    ${var:offset:number}
    取字串的最右側幾個字元,取字串的最右側幾個字元, 注意:冒號後必須有一空白字元
    ${var: -length}
    從最左側跳過offset字元,一直向右取到距離最右側lengh個字元之前的內容,即:掐頭去尾
    ${var:offset:-length}
    先從最右側向左取到length個字元開始,再向右取到距離最右側offset個字元之間的內容,注意:-length
    前空格,並且length必須大於offset
    $

3. 求10個隨機數的最大值與最小值。

1

	  awk 'BEGIN{srand();for (i=1;i<=10;i++)print int(rand()*100)}'> ./1.txt
	  cat ./1.txt|sort|head -1
	  cat ./1.txt|sort|tail -n 1 
2

	 num=($(awk 'BEGIN{srand();for (i=1;i<=10;i++)print int(rand()*100)}'))
	 echo ${num[0]}
	 echo ${num[-1]}

4. 使用遞迴呼叫,完成階乘演算法實現。

	fact(){
	if [ $1 -eq 1 ]; then
	   echo 1
	else
	   echo $[$1*$(fat $[$1-1])]
	fi
	}

5. 解析程序和執行緒的區別?

程序是程式執行時的一個例項,每個程序都有獨立記憶體空間、程式碼和資料以及其他系統資源,程序通訊需要透過管道和套接字等。
執行緒是程序內部中執行單元,程序中的執行緒共享相同的記憶體空間和其他資源,執行緒可以透過共享記憶體進行通訊。

6. 解析程序的結構。

1.文字段
包含了程序執行的程式機器語言指令。文字段具有隻讀屬性,以防止程序透過錯誤指標意外修改自身指令。因為多個程序可同時執行同一程式,所以又將文字段設為可共享,這樣,一份程式程式碼的複製可以對映到所有這些程序的虛擬地址空間中。

2.初始化資料段
包含顯示初始化的全域性變數和靜態變數。當程式載入到記憶體時,從可執行檔案中讀取這些變數的值。

3.未初始化資料段
包含了未進行顯示初始化的全域性變數和靜態變數。將經過初始化的全域性變數和靜態變數與未初始化的全域性變數和靜態變數分開存放,其主要原因在於程式在磁碟上儲存時,沒有必要為未經初始化的變數分配儲存空間。

4.棧
是一個動態增長和收縮的段,有棧幀(stack frames)組成。系統會為每個當前呼叫的函式分配一個棧幀。棧幀中儲存了函式的區域性變數(所謂自動變數)、實參和返回值。

5.堆(heap):是可在執行時(為變數)動態進行記憶體分配的一塊區域。堆頂端稱為program break。

7. 結合程序管理命令,說明程序各種狀態。

       D (TASK_UNINTERRUPTIBLE) 	不可中斷的深度睡眠,一般由IO引起,同步IO在做讀或寫操作時,cpu不能做其它事情,只能等待,這時程序處於這種狀態,如果程式採用非同步IO,這種狀態應該就很少見到了
       R (TASK_RUNNING)				正在執行,或在佇列中的程序
       S (TASK_INTERRUPTIBLE)		可中斷的睡眠狀態
       T (TASK_STOPPED)				停止狀態
       t (TASK_TRACED)				被跟蹤狀態
       Z (TASK_DEAD - EXIT_ZOMBIE)  退出狀態,但沒被父程序收屍,成為殭屍狀態
       W    						進入記憶體交換(從核心2.6開始無效)
       X (TASK_DEAD - EXIT_DEAD)    退出狀態,程序即將被銷燬
       I:空閒狀態(idle)
       B:程序正在等待更多的記憶體頁
       <    高優先順序
       N    低優先順序
       L    有些頁被鎖進記憶體
       s    包含子程序
       +    位於前臺的程序組;
       l    多執行緒,克隆執行緒  multi-threaded (using CLONE_THREAD, like NPTL pthreads do).

pstree 檢視程序,大部分情況下都為R執行程序

8. 說明IPC通訊和RPC通訊實現的方式。

IPC 是指程序之間的通訊方式,用於在同一臺計算機上的不同程序之間進行資料交換和通訊。
常見的 IPC 通訊方式包括管道、命名管道、訊息佇列、訊號量、共享記憶體和套接字等。
例如父程序建立了一個管道,並建立了一個子程序。父程序向管道中寫入一條訊息,而子程序從管道中讀取訊息並列印出來。

RPC 是指遠端過程呼叫,用於在網路上實現分散式系統中的遠端程式之間的通訊。
RPC 允許一個程式呼叫另一個程式中的函式或過程,就像呼叫本地函式一樣,而不需要程式設計師顯式地處理網路通訊細節。
比如我在外部主機有一個呼叫資源計算的程式,當我內部主機需要計算時透過呼叫外部主機的程式去實現

10. 總結Linux,前臺和後臺作業的區別,並說明如何在前臺和後臺中進行狀態轉換。

前臺程序:是在終端中執行的命令,那麼該終端就為程序的控制終端,一旦這個終端關閉,這個程序也隨之消失。

後臺程序:也叫守護程序,是執行在後臺的一種特殊程序,不受終端控制,它不需要終端的互動。

& 用在一個命令的最後,可以把這個命令放到後臺執行
<Ctrl>+z 將一個正在前臺執行的命令放到後臺,並暫停

11. 總結核心設計流派及特點。

單核心(Monolithic Kernel):
特點:單核心將所有核心功能和驅動程式放在一個大的核心空間中執行。核心負責管理硬體、記憶體、程序和檔案系統等。典型的單核心包括 Linux 核心和 Windows NT 核心。
微核心(Microkernel):
特點:微核心將最小的功能放在核心中,其他功能透過使用者空間的服務或伺服器來實現。例如,裝置驅動程式和檔案系統可以作為使用者空間服務執行。
混合核心(Hybrid Kernel):
特點:混合核心綜合了單核心和微核心的特點,將一些核心功能放在核心中,而將其他功能作為可選模組或使用者空間服務。

12. 總結rocky 啟動流程,grub工作流程

啟動流程:
1.BIOS/UEFI 初始化:系統開始啟動時,首先進行硬體初始化和自檢,然後載入載入程式。
2.在查詢(0號磁頭0號磁軌1扇區磁碟的前446位元組,後面的是硬碟分割槽表)MBR後,將MBR裝載到RAM中,bios將控制權交給MBR
3.MBR透過bootloader找到gurb.cfg,找到並載入模組和核心。
4.核心載入initranmfs.img(liunx精簡版,用於驅動掛載根)到記憶體去掛載根。
Init 程序替換:Linux 核心啟動後,Systemd 作為第一個使用者空間程序啟動,並替換掉 init 程序。
Systemd 啟動:Systemd 開始啟動系統中的各種單元(units),包括系統服務單元、掛載點、裝置單元等。它會按照單元之間的依賴關係和優先順序順序逐個啟動。
Target 單元:Systemd 使用 target 單元來組織系統啟動過程。CentOS 7 預設的 target 單元是 multi-user.target,它類似於傳統的執行級別3,表示多使用者文字模式。
服務單元啟動:Systemd 會啟動在啟動過程中所需的各種服務單元,如網路服務、日誌服務、檔案系統掛載等。這些服務單元的啟動順序可能會根據它們的依賴關係而有所調整。
使用者登入:一旦系統啟動完成並且所有服務都正常啟動,使用者可以登入到系統中進行操作。

gurb工作流程:
階段 1:
Stage 1 是GRUB的初始階段,也稱為引導載入程式。
它位於MBR(Master Boot Record)中的前446個位元組。
主要任務是載入階段 1.5或階段 2。
Stage 1 通常不足以直接載入核心,因此它會跳轉到其他階段。
階段 1.5:
Stage 1.5 是GRUB1中的一個特殊階段,已經在GRUB2中被完全移除。
它位於MBR之後的一小段空間中。
主要用於讀取檔案系統的內容,例如載入GRUB配置檔案和核心映像。
如果存在Stage 1.5,它會被載入並進一步載入階段 2。
階段 2:
Stage 2 是GRUB的最終階段,也稱為核心引導載入程式。
它位於磁碟上的檔案系統中,通常在/boot/grub目錄下。
主要任務包括:
顯示GRUB選單,允許使用者選擇作業系統或核心。
載入核心(通常是vmlinuz)和initramdisk(如果需要)到記憶體。
將控制權傳遞給核心,從而啟動作業系統。

13. 手寫chkconfig服務指令碼,可以實現服務的開始,停止,重啟。-

	#!/bin/bash

	#
	# chkconfig: 345 95 20
	# description: Example service script

	# Source function library.
	. /etc/init.d/functions

	# Define variables
	SERVICE_NAME="test"
	SERVICE_BIN="/usr/local/test/bin/test"
	PID_FILE="/var/run/test.pid"



	start() {
		echo "Starting $SERVICE_NAME..."
		$SERVICE_BIN
	}

	stop() {
		echo "Stopping $SERVICE_NAME..."
		killproc -p $PID_FILE $SERVICE_NAME
	}

	status() {
	if [ -f $PIDF ];then
		  echo "Nginx is running."
		else
		  echo "Nginx is stopped."
		fi
	}

	restart() {
		stop
		start
	}


	case "$1" in
		start)
			start
			;;
		stop)
			stop
			;;
		status)
			status
			;;
		restart)
			restart
			;;
		*)
			echo "Usage: $0 {start|stop|restart|status}"
			exit 1
			;;
	esac

	exit 0

14. 總結systemd服務配置檔案

例子:

	[Unit]
	Description=The nginx HTTP and reverse proxy server
	After=network.target remote-fs.target nss-lookup.target

	[Service]
	Type=forking
	PIDFile=/run/nginx.pid
	# Nginx will fail to start if /run/nginx.pid already exists but has the wrong
	# SELinux context. This might happen when running `nginx -t` from the cmdline.
	# https://bugzilla.redhat.com/show_bug.cgi?id=1268621
	ExecStartPre=/usr/bin/rm -f /run/nginx.pid
	ExecStartPre=/usr/sbin/nginx -t
	ExecStart=/usr/sbin/nginx
	ExecReload=/bin/kill -s HUP $MAINPID
	KillSignal=SIGQUIT
	TimeoutStopSec=5
	KillMode=mixed
	PrivateTmp=true

	[Install]
	WantedBy=multi-user.target

Unit:該部分包含關於服務單元的基本資訊。(不一定需要)
Description:描述服務的資訊。
After:指定服務應該在哪些其他單元之後啟動。在本例中,指定在網路服務啟動之後啟動該服務。

Service:該部分包含有關服務如何執行的詳細資訊。(最簡單隻需要ExecStart和type)
Type:指定服務的型別,可以是 simple、forking、oneshot、dbus 等。在本例中,指定為 simple,表示服務以簡單方式啟動。
PIDFile:指定主程序的PID檔案路徑
ExecStartPre :啟動nginx服務前做的命令
ExecStart:指定服務啟動時要執行的命令或程式。
ExecReload:當需要重新載入Nginx的配置執行命令
KillSignal:指定停止服務時的訊號
TimeoutStopSec:指定服務停止的超時時間
KillMode:指定服務的殺死模式
PrivateTmp:是否啟用私有臨時目錄,使得服務在執行過程中擁有獨立的臨時目錄,提高安全性。
Restart:指定當服務發生故障時是否自動重啟。

Install:該部分指定了如何安裝服務。
WantedBy:指定服務應該在哪些目標之中啟用。在本例中,指定為 multi-user.target,表示在多使用者環境中啟用該服務。

總結system啟動流程15. 總結system啟動流程

Systemd使用“target”來處理引導和服務管理過程。這些systemd裡的“target”檔案被用於分組不同的引導單元以及啟動同步程序。

在啟動過程中,systemd有幾個大目標,每個目標以.target表示。systemd的target主要作用是對多個任務進行分組,比如basic.target中,可能包含了很多工。

第一個大目標:sysinit.target
sysinit.target主要目的是讀系統執行環境做初始化,初始化完成後進入下一個大目標
第二個大目標:basic.target
basic.target的作用主要是在環境初始化完成後執行一些基本任務,算是做一些早期的開機自啟動任務,basic.target完成後進入第三個大目標
第三個大目標:『default.target執行級別』
default.target是一個軟連結,連結到不同的target表示進入不同的『執行級別』,執行級別階段的目的是為最終的登入做準備:

 如果是核心啟動過程中(核心啟動時呼叫了整合在initramfs中的systemd就處於這個過程),那麼大目標是initrd.target,該target的目標是為後續虛根切換到實根做初始化準備,比如檢查並掛載根檔案系統,最終虛根切換實根,並進入真正的使用者空間,也即完成了核心啟動或核心已經成功登入

  如果不是核心啟動過程中,可能會選擇不同的『執行級別』,通常是圖形終端的graphical.target,或者多使用者的執行級別multi-user.target,它們的目標都是完成系統啟動,並準備讓使用者登入系統

簡要過程
1.systemd執行的第一個目標是default.target。(但實際上default.target是指向graphical.target的軟連結。)
2.在這個階段,會啟動multi-user.target而這個target將自己的子單元放在目錄“/etc/systemd/system/multi-user.target.wants”裡。(這個target為多使用者支援設定系統環境。非root使用者會在這個階段的引導過程中啟用。防火牆相關的服務也會在這個階段啟動。)
接著"multi-user.target"會將控制權交給另一層“basic.target”。
3."basic.target"單元用於啟動普通服務特別是圖形管理服務。它透過/etc/systemd/system/basic.target.wants目錄來決定哪些服務會被啟動,basic.target之後將控制權交給sysinit.target.
4."sysinit.target"會啟動重要的系統服務例如系統掛載,記憶體交換空間和裝置,核心補充選項等等。
5.ysinit.target在啟動過程中會傳遞給local-fs.target
local-fs.target,這個target單元不會啟動使用者相關的服務,它只處理底層核心服務。這個target會根據/etc/fstab和/etc/inittab來執行相關操作。

16. 總結awk工作原理,awk命令,選項,示例。

AWK 原理:
文字處理: AWK 是一種程式語言,用於在文字檔案中搜尋和處理模式。
模式匹配: 它透過定義模式來匹配文字行,並對匹配的行執行指定的操作。
資料欄位: AWK 自動將每行分割成欄位,可以單獨處理每個欄位。
程式設計結構: 支援條件語句、迴圈和陣列,適合複雜文字處理任務。

選項:

-F <分隔符> 或 --field-separator=<分隔符>: 指定輸入欄位的分隔符,預設是空格。使用這個選項可以指定不同於預設分隔符的欄位分隔符。
例子:awk -F ":" '{print $1 ":" $3 }' exe.txt 以:為分隔符

-v <變數名>=<值>: 設定 awk 內部的變數值。可以使用該選項將外部值傳遞給 awk 指令碼中的變數。變數只按變數為分隔符分割,跟行列沒關係
例子:awk -v FS=":" '{print $FS$3}' /etc/passwd 變數呼叫

-f <指令碼檔案>: 指定一個包含 awk 指令碼的檔案。這樣可以在檔案中編寫較大的 awk 指令碼,然後透過 -f 選項將其載入。
例子:awk -F'[ .]' '{print $2}' exe.log

17. 總結awk的陣列,函式。

陣列
awk支援索引陣列和關聯陣列兩種型別的陣列。
索引陣列以數字作為索引,從0開始遞增,用於按順序儲存資料。
關聯陣列以字串作為索引,也稱為鍵,用於根據特定鍵檢索資料。
陣列元素可以透過索引或鍵來訪問,也可以透過迴圈遍歷陣列中的所有元素。

awk 'BEGIN{ fruits[0]="apple"; fruits[1]="banana"; for(i=0;i<2;i++) print fruits[i] }'

函式
awk支援自定義函式,可以用於封裝常用的操作和邏輯。
函式可以接受引數並返回值。
在awk中,函式可以像內建函式一樣使用,並且可以在指令碼中任何地方呼叫。

# 定義函式
function add(x, y) {
	return x + y
}

# 呼叫函式
awk 'BEGIN{ result = add(2, 3); print result }'

18. 總結ca管理相關的工具,根據使用場景總結示例。

OpenSSL:
使用場景:自簽名證書、證書籤發、證書籤名請求生成等。
示例:
生成自簽名證書:openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365
生成證書籤發請求:openssl req -new -key key.pem -out req.pem
簽發證書:openssl x509 -req -in req.pem -CA cert.pem -CAkey key.pem -CAcreateserial -out cert_signed.pem -days 365
EasyRSA:
使用場景:快速搭建PKI(Public Key Infrastructure)環境,管理CA證書和使用者證書。
示例:
初始化PKI環境:easyrsa init-pki
生成CA證書和私鑰:easyrsa build-ca
簽發使用者證書:easyrsa build-client-full user1 nopass
生成伺服器證書:easyrsa build-server-full server1 nopass
cfssl(CloudFlare SSL):
使用場景:基於JSON配置檔案進行CA證書管理,支援自簽名證書、證書籤發和撤銷等操作。
示例:
生成自簽名證書:cfssl selfsign domain-csr.json | cfssljson -bare domain
生成證書籤發請求:cfssl gencert -initca csr.json | cfssljson -bare cert
簽發證書:cfssl sign -ca cert.pem -ca-key key.pem csr.json | cfssljson -bare cert

19. 總結對稱加密和非對稱加密演算法和用openssl簽發證書步驟

對稱加密:
對稱加密使用相同的金鑰(稱為對稱金鑰)進行加密和解密。
加密和解密過程使用相同的金鑰,因此速度較快。
常見的對稱加密演算法包括DES(Data Encryption Standard)、AES(Advanced Encryption Standard)、3DES等。
由於金鑰是相同的,因此對稱加密演算法的金鑰管理相對簡單。
主要缺點是金鑰分發和管理的安全性問題,需要確保金鑰在傳輸和儲存過程中不被洩露。
非對稱加密:
非對稱加密使用一對金鑰進行加密和解密,分別稱為公鑰和私鑰。
公鑰用於加密資料,私鑰用於解密資料,或者用於數字簽名和身份驗證。
加密過程使用公鑰進行,解密過程使用私鑰進行。
常見的非對稱加密演算法包括RSA(Rivest-Shamir-Adleman)、DSA(Digital Signature Algorithm)、ECC(Elliptic Curve Cryptography)等。
非對稱加密演算法的主要優點是金鑰分發相對簡單,公鑰可以公開傳輸,私鑰只有持有者知曉。
但是由於非對稱加密演算法的計算複雜度較高,速度較慢,因此一般用於金鑰交換、數字簽名等場景。

openssl簽發證書步驟
1、建立CA所需要的檔案
1.1生成證書索引資料庫檔案
touch /etc/pki/CA/index.txt
1.2指定第一個頒發證書的序列號
echo 01 > /etc/pki/CA/serial
2.生成CA私鑰
cd /etc/pki/CA/
(umask 066; openssl genrsa -out private/cakey.pem 2048)
3、生成CA自簽名證書
openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -days 3650 -out
/etc/pki/CA/cacert.pem
選項說明:
-new:生成新證書籤署請求
-x509:專用於CA生成自簽證書
-key:生成請求時用到的私鑰檔案
-days n:證書的有效期限
-out /PATH/TO/SOMECERTFILE: 證書的儲存路徑

自簽名證書需要填寫的資料
國家、省份、城市、公司、部門、域名、郵箱
自簽名證書需要與後面發的證書中的3點一致(如果沒有更改策略 更改總策略:policy =policy_anything 或者更改單一策略)
國家、省份、公司

申請證書並頒發證書
1、為需要使用證書的主機生成生成私鑰
(umask 066; openssl genrsa -out /data/test.key 2048)
2、為需要使用證書的主機生成證書申請檔案(需要與前邊CA的3點一致)
openssl req -new -key /data/test.key -out /data/test.csr
3、CA簽署證書
openssl ca -in /data/test.csr -out /etc/pki/CA/certs/test.crt -days 100
4、傳送證書
直接複製檔案、郵件傳送、使用安全傳輸協議、儲存到網路共享目錄、使用配置管理工具等等

相關文章