18. ubuntu的實踐——who,ln,inxi,內核,編譯

2020-08-12 10:43:04

18.who

who命令列印有關當前登錄的所有使用者的資訊。

18.1.who語法

who [ OPTION ]… [ FILE ] [ am i ]

  • 選項
參數 意義
-a, --all 與使用選項-b -d --login -p -r -t -T -u相同。
-b, --boot 顯示上次系統引導的時間。
-d, --dead 顯示死進程。
-H, --heading 列印一行列標題。
–ips 列印IP地址而不是主機名。 使用–lookup,基於儲存的IP(如果可用)進行規範化,而不是儲存的主機名。
-l, --login 列印系統登錄過程。
–lookup 嘗試通過DNS規範化主機名。
-m 僅列印有關與標準輸入(發出命令的終端)關聯的使用者和主機的資訊。 此方法符合POSIX標準。
-p, --process 列印由init生成的活動進程。
-q, --count 顯示所有登錄名,以及所有登錄使用者的計數。
-r, --runlevel 列印當前執行級別。
-s, --short 僅列印名稱,行和時間欄位,這是預設值。
-t, --time 如果資訊可用,則列印上次更改系統時鐘的時間。
-T, -w, --mesg 新增一個字元,該字元指示終端的狀態:「+」如果終端是可寫的,「-」如果終端不是可寫的,或「?」
-u, --users 列印每個使用者的空閒時間和進程ID。
–message 與-T相同。
–writable 與-T相同。
–help 顯示幫助訊息,然後退出。
–version 顯示版本資訊,然後退出。
  • 筆記

如果指定了檔案,則由誰從該檔案收集其資訊。否則,它將從預設檔案位置(通常是/var/run/utmp)讀取。
如果指定了參數「am i」,則who假定爲-m選項。
who範例:hlx@NLP:~$ who
版本檢視:hlx@NLP:~$ who --version
在这里插入图片描述

顯示當前所有登錄對談的使用者名稱、行和時間。例如:
who am i
顯示相同的資訊,但僅用於發出命令的終端對談,例如:
linuxmi pts/3 2018-12-02 08:52 (:0.0)
顯示「所有」資訊以及每列數據上方的標題,例如:
linuxidc@linuxidc:~$ who -aH
名稱 線路 時間 空閒 進程號 備註 退出
系統引導 2018-12-02 07:45
執行級別 5 2018-12-02 07:46
linuxidc ? :0 2018-12-02 07:47 ? 4569 (:0)
在这里插入图片描述

19.命令ln

符號鏈接,也稱爲符號鏈接或軟鏈接, 是一種指向另一個檔案或目錄的特殊型別的檔案。
在本指南中,我們將介紹如何使用ln命令建立符號鏈接。

19.1.鏈接型別

Linux/UNIX系統中有兩種型別的鏈接:

  • 硬鏈接。您可以將硬鏈接視爲現有檔案的附加名稱。硬鏈接將兩個或多個檔名與相同的inode相關聯。您可以爲單個檔案建立一個或多個硬鏈接。無法爲目錄和不同檔案系統或分割區上的檔案建立硬鏈接。
  • 軟鏈接。軟鏈接類似於Windows中的快捷方式。它是指向檔案或目錄的間接指針。與硬鏈接不同,符號鏈接可以指向不同檔案系統或分割區上的檔案或目錄。

19.2.命令

ln是用於在檔案之間建立鏈接的實用程式。預設情況下,ln命令會建立硬鏈接。要建立符號鏈接,請使用-s(–symbolic)選項。
ln命令語法如下:
ln [OPTIONS] FILE LINK

19.3.建立符號鏈接

要在Linux中建立符號鏈接,請開啓終端並鍵入:
ln -s source_file symbolic_link
將source_file替換爲要爲其建立符號鏈接的現有檔案的名稱,將symbolic_link替換爲符號鏈接的名稱。
symbolic_link參數是可選的。 如果未指定符號鏈接,則ln命令將在當前目錄中建立新鏈接。

19.3.1.建立符號鏈接到檔案

在以下範例中,我們將建立名爲tmpfile_link.txt的符號鏈接到名爲tmpfile.txt的檔案:
hlx@NLP:~/umake/tmp$ ln -s tmpfile.txt tmpfile_link.txt
要驗證是否已建立符號鏈接,請使用ls命令:
hlx@NLP:~/umake/tmp$ ls -l tmpfile_link.txt
範例
在这里插入图片描述

l字元是表示符號鏈接的檔案型別標誌。 ->符號顯示符號鏈接指向的檔案。

19.3.2.建立符號鏈接到目錄

用於建立指向目錄的符號鏈接的命令與建立指向檔案的符號鏈接時的命令相同。 將目錄名稱指定爲第一個參數,將符號鏈接指定爲第二個參數。
例如,如果要建立從/test/目錄到/umake/目錄的符號鏈接,則執行:
hlx@NLP:~/umake/tmp$ ln -s ~/test/ ~/umake/
在这里插入图片描述

19.3.3.覆蓋符號鏈接

如果您嘗試建立已存在的符號鏈接,則ln命令將列印錯誤訊息。
hlx@NLP:~/umake/tmp$ ln -s tmpfile.txt tmpfile_link.txt

在这里插入图片描述

要覆蓋符號鏈接的目標路徑,請使用-f(–force)選項。
hlx@NLP:~/umake/tmp$ ln -sf tmpfile.txt tmpfile_link.txt

19.3.4.刪除符號鏈接

您可以使用unlink或rm命令刪除/刪除現有的符號鏈接。
unlink命令語法非常簡單:
hlx@NLP:~/umake/tmp$ unlink tmpfile_link.txt
在这里插入图片描述

使用rm命令刪除符號鏈接與刪除檔案相同:
rm symlink_to_remove
您應該更喜歡使用unlink實用程式來刪除符號鏈接。
如果刪除原始檔或將其移動到其他位置,則符號檔案將保持懸空狀態。 你應該刪除它,因爲它將不再起作用。

20.inxi

要在Ubuntu命令控制檯中檢查系統資訊和硬體詳細資訊,而不與各種Linux命令混淆,可以使用功能齊全的CLI系統資訊。
Ubuntu軟體中已經有一個很棒的圖形工具Hardinfo。 對於命令列工具,可以使用inxi檢查:

  • 音訊/音效卡,驅動程式,聲音伺服器。
  • 系統電池資訊
  • CPU輸出
  • 硬碟資訊
  • 顯示卡,驅動程式,顯示伺服器,解析度,渲染器,OpenGL版本。
  • 一般資訊,包括進程,正常執行時間,記憶體,IRC用戶端或shell型別,inxi版本。
  • 記憶體(RAM)數據(需要root)
  • 網絡卡,驅動程式。
  • 系統資訊,分割區資訊,感測器輸出,USB數據等。

inxi - 控制檯和IRC的命令列系統資訊指令碼
要在Ubuntu中安裝inxi,只需執行命令:
linuxidc@linuxidc:~$ sudo apt-get install inxi
在这里插入图片描述

然後執行man inxi以獲取命令選項列表
在这里插入图片描述

或執行inxi -F以獲得簡短輸出:
linuxidc@linuxidc:~$ inxi -F
在这里插入图片描述

但是如果你想要更多資訊怎麼辦?
不要擔心命令充滿了選項,有些是:

  • -A 顯示音訊/音效卡資訊。
  • -C 顯示完整的CPU輸出,包括每CPU時鐘速度。
  • -D 顯示完整的硬碟資訊,不僅是型號,即:/dev/sda model: VMware_Virtual_S size: 32.2GB
  • -F顯示inxi的完整輸出。 包括所有大寫字母系列字母,加上-s和-n。
  • 除非您使用該參數,否則不會顯示額外的詳細選項,例如-x -d -f -u -l -o -p -t -r。
  • -G顯示圖形卡資訊(卡,x型別,解析度,glx渲染器,版本)。
  • -I顯示資訊:進程,正常執行時間,記憶體,irc用戶端,inxi版本。
  • -l顯示分割區標籤。 預設值:短分割區-P。 對於完整的-p輸出,請使用:-pl(或-plu)。
  • -n顯示高階網絡卡資訊。 與-Nn相同。 顯示介面,速度,mac id,狀態等。
  • -N顯示網絡卡資訊。 使用-x,顯示PCI BusID,埠號。

最後一點,如果您使用的是Xterm,您可以選擇使用哪種配色方案,並檢視哪個配方可用,只需使用命令:inxi -c 94,您將獲得與此類似的輸出:

在这里插入图片描述

21.檢視linux內核

如何找到Linux內核版本
在撰寫本文時,我正在使用Ubuntu 18.04。但是這些命令是通用的,可以在Fedora,Debian,CentOS,SUSE Linux或任何其他Linux發行版上使用。

21.1.使用uname命令查詢Linux內核

uname是用於獲取系統資訊的Linux命令。您也可以使用它來確定您使用的是32位元還是64位元系統。
開啓一個終端並使用以下命令:
hlx@NLP:~$ uname -r
輸出將類似於以下內容:
4.15.0-76-generic
在这里插入图片描述

這意味着您正在執行Linux內核5.3.0-28,或者更籠統地說,您正在執行Linux內核版本5.3。
但是其他數位在這裏意味着什麼? 讓我向您解釋一下:

  • 5 –內核版本
  • 3 –重大修訂
  • 0 –輕微修訂
  • 28 –錯誤修復

generic–特定於版本的字串。 對於Ubuntu,這意味着我正在使用桌面版本。 對於Ubuntu伺服器版本,它應該是server。
您還可以將uname命令與-a選項一起使用。 如果需要,這將提供更多的系統資訊。
hlx@NLP:~$ uname -a
輸出將類似於以下內容:
Linux NLP 4.15.0-76-generic #86~16.04.1-Ubuntu SMP Mon Jan 20 11:02:50 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
在这里插入图片描述

讓我解釋一下輸出並賦予它一個含義::

  • Linux –內核名稱。 如果在BSD或macOS上執行相同的命令,結果將有所不同。
  • NLP –主機名
  • 5.3.0-28-generic –內核版本(我們剛剛說過了)
  • #86~16.04.1-Ubuntu SMP Mon Jan 20 11:02:50 UTC 2020 – 這意味着Ubuntu編譯了5.3.0-28-generic 30次。最後的編譯時間戳也在那裏。
  • x86_64 –機器架構
  • x86_64 –處理器架構
  • x86_64 –操作系統體系結構(您可以在64位元處理器上執行32位元OS)
  • GNU/Linux –操作系統(不,它不會顯示發行名稱)
    我會幫你避免資訊超載。所以讓我們看看其他命令來查詢Linux內核版本。

21.2.使用/proc/version檔案查詢Linux內核

在Linux中,您還可以在檔案/proc/version中找到Linux內核資訊。 只需檢視此檔案的內容即可:
hlx@NLP:~$ cat /proc/version
您會看到類似於我們用uname看到的輸出。

Linux version 4.15.0-76-generic (buildd@lgw01-amd64-023) (gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.12)) #86~16.04.1-Ubuntu SMP Mon Jan 20 11:02:50 UTC 2020

您可以在此處看到內核版本4.15.0-76-generic
在这里插入图片描述

21.3.使用dmesg命令查詢Linux內核版本

dmesg是用於編寫內核訊息的功能強大的命令。 在獲取系統資訊時也非常有用。
由於dmesg提供了很多資訊,因此您應該使用類似less的命令來閱讀它。 但是由於您只是在這裏檢查Linux內核版本,因此在Linux上進行grepping應該會提供所需的輸出。
hlx@NLP:~$ dmesg | grep Linux
輸出只有幾行,但是您應該能夠很容易地識別出Linux內核版本。

[ 0.000000] Linux version 4.15.0-76-generic (buildd@lgw01-amd64-023) (gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.12)) #86~16.04.1-Ubuntu SMP Mon Jan 20 11:02:50 UTC 2020 (Ubuntu 4.15.0-76.86~16.04.1-generic 4.15.18)
[ 0.104840] ACPI: Added _OSI(Linux-Dell-Video)
[ 0.104840] ACPI: Added _OSI(Linux-Lenovo-NV-HDMI-Audio)
[ 0.104840] ACPI: Added _OSI(Linux-HPI-Hybrid-Graphics)
[ 0.913286] Linux agpgart interface v0.103
[ 0.917937] usb usb1: Manufacturer: Linux 4.15.0-76-generic xhci-hcd
[ 0.919326] usb usb2: Manufacturer: Linux 4.15.0-76-generic xhci-hcd
[ 0.975396] usb usb3: Manufacturer: Linux 4.15.0-76-generic xhci-hcd
[ 0.975786] usb usb4: Manufacturer: Linux 4.15.0-76-generic xhci-hcd
[ 1.031216] usb usb5: Manufacturer: Linux 4.15.0-76-generic xhci-hcd
[ 1.031610] usb usb6: Manufacturer: Linux 4.15.0-76-generic xhci-hcd
[ 1.622544] pps_core: LinuxPPS API ver. 1 registered
[ 4.043989] Intel® Wireless WiFi driver for Linux
on the primary VGA device. The NVIDIA Linux graphics driver

在这里插入图片描述

22.編譯相關命令

22.1.編譯可執行檔案

  • 方法一:
    g++ –c Hello.cpp 編譯檔案,生成目標檔案Hello.o
    g++ Hello.o –o a.out 鏈接並重新命名爲可執行檔案a.out
    在这里插入图片描述

  • 方法二:
    g++ Hello.cpp 編譯鏈接一起,生成a.out
    在这里插入图片描述

  • 方法三
    g++ Hello.cpp –o hello 生成a.out並命名爲hello
    在这里插入图片描述

22.2.編譯相關選項

(1)-c
生成.o檔案,對程式碼檔案進行預處理、編譯和彙編,相當於windows下生成目標檔案obj
g++ -c hello.cpp

(2)-I DirPath
指定檔案查詢目錄
-include file
-i file
指定包含的檔案
g++ hello.cpp -include …/include/a.h
-I- DirPath
就是取消前一個參數的功能,所以一般在-I DirPath之後使用

(3)-L LibPath
指定鏈接庫的路徑
-l library
-llibrary
指定鏈接庫

(4) -g
在編譯的時候,產生偵錯資訊,程式執行時可以dbg偵錯

(5)-static
此選項將禁止使用動態庫。
優點:程式執行不依賴於其他庫
缺點:檔案比較大
gcc test_main.c -static -o test_main -lpthread
會發現test_main很大,它已經把各種依賴的東西都包含進來

(6)-shared (-G)
此選項將盡量使用動態庫,爲預設選項
優點:生成檔案比較小
缺點:執行時需要系統提供動態庫

(7)-Wall
一般使用該選項,允許發出GCC能夠提供的所有有用的警告。也可以用-W{warning}來標記指定的警告。

22.3.靜態庫和動態庫的編譯命令

22.3.1.生成動態庫和靜態庫

(1)得到hello.o
g++ -c hello.cpp

(2)得到靜態庫myhello.a
ar -cr libmyhello.a Hello.o
在这里插入图片描述

(3)使用靜態庫
g++ -o hello main.c -L. -lmyhello
-L.表示靜態庫位於當前目錄下,myhello自動加上lib組成靜態庫名稱libmyhello.a

(4)得到動態庫myhello.so
hlx@NLP:~/umake/tmp/cpp$ g++ -fPIC -shared Hello.cpp -o libmyhello.so
在这里插入图片描述

(5)使用動態庫
動態庫的時候和靜態庫使用一樣,唯一值得注意的是當目錄中同時存在相同名稱的動態庫和靜態庫時,編譯的時候優先使用動態庫

22.3.2.fPIC選項

加上fPIC選項生成的動態庫時位置無關的,可以實現多個進程共用動態庫,多個進程參照同一個PIC動態庫時,可以共用記憶體。這一個庫在不同進程中的虛擬地址不同,但操作系統顯然會把它們對映到同一塊實體記憶體上。
不加fPIC,則載入so檔案時,需要對程式碼段參照的數據物件需要重定位,重定位會修改程式碼段的內容,這就造成每個使用這個.so檔案程式碼段的進程在內核裡都會生成這個.so檔案程式碼段的copy.每個copy都不一樣,取決於這個.so檔案程式碼段和數據段記憶體對映的位置。可見,這種方式更消耗記憶體。

22.3.3.如何解決執行時找不到動態庫的問題

(1)將動態庫新增到系統預設的搜尋路徑下,如/lib、/usr/lib
(2)設定臨時動態庫路徑的環境變數,這種方法設定的是臨時的,系統重新啓動之後就沒了
export LD_LIBRARY_PATH=./
取消設定
export LD_LIBRARY_PATH=
(3)/etc/ld.so.cache中快取了動態庫路徑,可以通過修改組態檔/etc/ld.so.conf中指定的動態庫搜尋路徑,然後執行ldconfig命令來改變
(4)編譯鏈接新增-WL,-rpath命令選項,將執行時動態庫的搜尋路徑記錄在可執行程式中
例如,有原始檔test.cpp和func.cpp
g++ -shared -fPIC func.cpp -o libfunc.so
編譯得到libfunc.so動態庫
g++ main.cpp -o a.out -L ./ -lfunc
編譯得到a.out,執行a.out,提示出錯
在这里插入图片描述

ldd檢視a.out依賴的動態庫,發現libfunc.so找不到
在这里插入图片描述

g++ main.cpp -o a.out -L ./ -lfunc -WL,-rpath ./
編譯得到a.out,執行a.out,執行成功,ldd檢視a.out依賴的動態庫,發現libfunc.so路徑正確
在这里插入图片描述
把a.out和libfunc.so拷貝到任何目錄下,都能執行成功