1. 程式人生 > >服務計算3 開發 Linux 命令列實用程式

服務計算3 開發 Linux 命令列實用程式

文章目錄

概述

本次作業參考潘老師的部落格
https://pmlpml.github.io/ServiceComputingOnCloud/ex-cli-basic

github傳送門
https://github.com/ddghost/Sevice-Computing/tree/CLI-命令列實用程式開發基礎

本次作業主要是編寫一個命令列程式,處理標準輸入或者文字檔案。程式的要求主要參考、https://www.ibm.com/developerworks/cn/linux/shell/clutil/index.html

1.解析引數

對於命令列程式,首先要做的就是解析命令列傳入的引數,例如執行程式

./selpag -s 1 -e 1 input.txt

對於這個命令,我們這個程式應該要至少有三個變數,一個記錄-s後的1,一個記錄-e後的1,一個記錄input.txt。
傳入的引數是命令列程式最重要的東西。解析可以使用os庫裡的os.Args,但是這很麻煩。
所幸已經有前人幫我們完成解析引數的工作,那就是使用flag或者pflag庫。這兩個庫的使用可以參考
https://o-my-chenjian.com/2017/09/20/Using-Flag-And-Pflag-With-Golang/

在命令列輸入以下程式碼獲得pflag包,而flag包不用獲取

go get github.com/spf13/pflag

由於老師要求使用pflag,這裡給出pflag簡單的程式碼使用,例如對於IntVarP,五個引數分別是,變數的地址,長名,短名,預設值,幫助時的語句。

	flag.IntVarP(&page_len , "l", "l" , 72, "page length")
	flag.BoolVarP(&help , "h", "h", false, "show help")
	flag.StringVarP(&print_dest , "d", "d" , "", "print detination")

對於傳入的引數,以下兩種情況是等價的,它們都會把page_len賦值為11。

./selpage -l 11
./selpage -l=11
./selpage --l 11
./selpage --l=11

將變數名和傳入的引數繫結後,使用parse就可以解析了,注意不要忘了,否則忘了解析各變數的值都是預設的。

flag.parse()

對於傳入的前面是‘-’的引數,可以用pflag提前繫結好變數,但是這次傳入的檔名引數,前面是沒有‘-’的,這裡只要注意 pflag 會把不能解析的引數都放在Args()數組裡面,因此呼叫flag.Args()[0]就可以獲得第一個沒被解析成flag的引數,也就是檔名。

2.命令列的’<’,’>’,’|'符號

在實現要求中,展示了程式在命令列中搭配’<’ , ‘>’ , ‘|’ 符號的操作,我對命令列的操作並不是太熟悉,開始還很奇怪為什麼輸入之後用pflag解析不了。
後來發現這些符號的效果並不需要我們實現,它們是linux命令列自帶的效果,和‘&’符號一樣。

3.執行命令列的命令

本部分參考
https://godoc.org/os/exec#example-Command

在本次作業中,需要在程式裡執行一個命令列的命令lp,因此要用到os/exec包,簡要的程式碼如下。
exec.Command後面的傳入的引數就是命令列要執行的命令還有引數,例如想執行“cat tmp.txt“,就應該傳入"cat"和 “tmp.txt”,簡單來說就是將空格分開的部分分別寫進去。
然後cmd.StdinPipe()就是lp命令的輸入管道,lp的輸入接受本程式的輸出。
然後後面cmd.Start執行命令列程式。
如果3秒後還沒執行完,進行終止。

			cmd = exec.Command("lp" , "-d" , print_dest)
			fout, err = cmd.StdinPipe()
			if err != nil {
				fmt.Fprintln(os.Stderr, err)
				os.Exit(1) 
			}
			outputFile(inputFile , fout)
			fout.Close()
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			err = cmd.Start()
			if err != nil {
				fmt.Fprintln(os.Stderr, err)
				os.Exit(1) 
			}
			timer := time.AfterFunc(3*time.Second, func() {
				cmd.Process.Kill()
			})
			err = cmd.Wait()
			timer.Stop()

4.總結

還記得老師佈置作業的時候說這次作業很簡單,很快就能寫完,但是在國慶的時候我花了好幾天才寫完,光是文件都看了好久。最主要的問題還是對linux命令列很多東西都不是太熟悉,還有第一次寫go程式也不太熟練的緣故。