Linux 指令蒐集

蒐集 Linux 的指令用法,主要是 case by case 而非指令的詳細用法。並且指令也不侷限於此處提到的用法。故使用者有興趣可深入查詢研究。

  • 通用觀念
  • 管道是由右向左建立起來的。複合指令正確時無虞;但錯誤時,便需知道從右邊過來可能已産生既定的結果(例如建立一個檔案)
  • 變量:賦值時只以字串形式表示,取值時前綴$。myvar=ken; echo $myvar;
  • 可將命令執行結果賦予一變量,表示法:myvar=`date` 或 myvar=$(date)
  • 注意等號兩邊不允許有空格,因為如 myvar = ken 會解釋成執行 myvar 帶二個參數。
  • 可互動式地指定變量:read myvar,則 shell 會等待輸入,並賦予 myvar 該輸入值。
  • 命令行變量:例如執行 ls -l -a -R,那麼會産生對應的暫存變量 $0,$1,$2,$3 各代表 ls,-l,-a,-R 依此類推,以供當下運用(請注意是執行當中才有,故主要用於 script file 內)。另有 $# 代表總共有幾個參數,不含指令本身。上例是 3
  • $? 代表命令執行後的回傳值,其為 0 的話通常表示執行成功。
  • basename:basename /home/ken/a.txt 會得到 a.txt 字串
  • 參考

netcat

透過 TCP/IP 傳送封包,使用者自訂其內容。可建立傾聽端(服務端)(當該埠是未被佔用的),也可建立傳送端。

在本地端的 8088 埠(port)建立傾聽端(listener),ctrl-c 結束或單一 session 傳完也自動結束掉。

  • netcat -l -p 8088

建立傳送端,對象是本地的 8088 port

  • netcat localhost 8088

建立後,例如輸入 a,則 listener 會 dump 出 a。

測試

因為我們本地端已有 web server,故建立 sender,並發送 GET request 來查看回應。
但我現在更希望知道 GET request 長怎麼樣,故,我們先停止 web server,利用 firefox 發送來攫取:firefox 需鍵入網址 http://localhost/

抓到之後,再重新啟動 web server 後, 建立 localhost:80 sender,再把剛複製的 GET request 貼上,得到 web server 的回應如下

  • netcat localhost 80
  • 參考資料
  • -l listen
  • -p port
  • -u UDP instead of TCP
  • https://askubuntu.com/questions/443227/sending-a-simple-tcp-message-using-netcat
  • https://unix.stackexchange.com/questions/121230/nc-bind-failed-address-already-in-use/121244
  • https://ubuntuforums.org/showthread.php?t=2260190
  • https://unix.stackexchange.com/questions/366913/problem-running-a-web-server-in-oracle-vm-virtualbox-with-port-forwarding

history

其實對於新手或老手,history 都有相當多的用處。因為就算老手,仍會接觸到新的指令操作。又或是記性不好的使用者,像筆者就是。再或是追查何時下過什麼指令等等。新手會慢慢查覺 history 的諸多好處。

  • 在安裝 Ubuntu 時提到,bash shell 預設 history 就是不含時間戳記的下過的指令的記錄。其儲存在 user home 下的 .bash_history 文字檔案內,可 cat 出來看看。因此,在那篇就變更預設,成不限筆數及加入時間戳記。
  • shell 下下達 history 後,即可 dump 出來編上行號的指令歴史記錄。可下 “!行號”以執行該行指令。
  • 當時下過的指令會先暫存,若同時使用數個 shell,當最後一個 shell 關閉後,才會將最後一個關閉的 shell 所下過的指令寫入 .bash_history,其它先關閉的不會儲存。
  • 預設的記錄會長得像這樣:
    cd ~
    cp .bash_history ./Desktop/33.txt
  • 當加入時間戳記後,.bash_history 內容的每一筆記錄會長得像這樣
    #1577514000
    cd~
    #1577514019
    cp .bash_history ./Desktop/33.txt
    第一行是時間戳記,第二行是指令。
  • 本節旨在清理 history,將 .bash_history 中所有重覆下過的相同指令移除(例如,幾千筆記錄中,只會有唯一的一筆 ls -la,是不是很好玩)。我們該如何為之?重點不是清理,而是學習運用指令達到我們的目的。
  • 當不含時間戳記時:
  • cat -n .bash_history | tr -s [:blank:] ” ” | sort +1 -u | sort -n | cut -d ” ” -f3- (請注意雙引號字元)
  • 其中:
  • cat -n .bash_history 將記錄檔中的每一筆都加上流水號,我們目的是定序
  • tr -s [:blank:] ” “,將 [:blank:],其代表“空白字元”,其包含 space & TAB,轉成“ ”空白字元,並且(-s 的意思)連續出現的空白字元,縮減成一個,例如“ _ _ _ _ _ _”有六個 space,刪成“ _”只有一個 space (我們在每個空白符號後多加了個“_”不然使用者看不出什麼)
    sort +1 -u:一行中由空白字元分隔出若干個 field,例如 “just do it”有三個 fields,依序是 just,do,it。sort,排序,預設是由左而右逐個字元與其他行做比對。+1 指的是略過第一個 field,從第二個 field 開始排序。-u 是指,所有出現相同的,只留一筆。
    因此,至此,已清除重覆者,但時間順序已亂掉,我們由一開頭的定序,再排序一次,便可排回時間順序。sort -n 指的是從第一個 field 起以視為數字的形式來排。
  • cut 預設分隔符號是 TAB。我們以上使用 ” ” space,所以 -d ” ” 表示將 cut 認得的分隔符號換成 space(這表示我們處理的字串中也只能有 space 不能有 TAB,否則我們自己會亂掉。就這是為什麼我們開頭要把所有空白字元全轉成 space)。並且 cut 每遇到一個分隔符號便會累計個數。-f 表示從哪個 field 開始剪下。3- 表示從第三個 field 及以後的剪下保留。
    最後導出入另一個檔案便是不重覆的歴史記錄了。
  • 當含時間戳記時,只要將相鄰兩行合併,就回到第一個問題了,使用者可嘗試看看。
  • 將相鄰兩行合併:xargs -n2 -d’\n’
  • 將合併的再分開:sed ‘s/\(#[0-9]*\) \(.*\)/\1\n\2/’
  • cat .bash_history | xargs -n2 -d’\n’ | cat -n | tr -s [:blank:] ” ” | sort +2 -u | sort -n | cut -d ” ” -f3- | sed ‘s/\(#[0-9]*\) \(.*\)/\1\n\2/’(請注意單雙引號字元)
  • | 稱之為管線,將前一段指令的執行的標準輸出結果導到下一段指令做為輸入。若使用者的結果有誤,可逐段執行先觀看其結果符不符合預期。


參考資料:
https://unix.stackexchange.com/questions/102008/how-do-i-trim-leading-and-trailing-whitespace-from-each-line-of-some-output
https://stackoverflow.com/questions/3134791/how-do-i-remove-newlines-from-a-text-file
https://www.grymoire.com/Unix/Sed.html

inotify

  • https://github.com/rvoicilas/inotify-tools/wiki
  • https://stackoverflow.com/questions/47673447/inotify-linux-watching-subdirectories/49345762#49345762
  • https://github.com/tinkershack/fluffy

netstat

  • netstat -nputw

以數值的形式(n,其避免了伴隨可能的長程的 DNS 查詢)列出所有 UDP(u),TCP(t),和 RAW(w) 對外的連線(w 相對於 l 和 a),並包含了使用它的程式(p)。外加 c 參數的話可持續更新。

列出手動安裝的套件

  • 筆者搜尋到一種方法,其目的毌待贅言。
  • comm -23 <(apt-mark showmanual | sort -u) <(gzip -dc /var/log/installer/initial-status.gz | sed -n ‘s/^Package: //p’ | sort -u) (注意引號)

RamDisk

  • 對於頻繁存取硬碟的應用程式我們可以創建 ramdisk 讓它使用以延長磁碟壽命。速度的提升自不在話下。
  • ramdisk 的空間大小,當然相依於所安裝的 ram 的空間大小。ram 留個 4 GB 給系統用應已足夠;不過還是得依實際情況而定。而剩下的可挪為 ramdisk 之用。但使用 ramdisk 並非常態,除非必要。
  • 筆者的 ram 有 16GB,有時抓些影片會使用 emule。故跑它時會建立 10 GB 的 ramdisk 空間給它用。
  • 先建立一個目錄,做為 ramdisk 的映射目錄。因只是儲存目的,所以設最低權限
  • sudo mkdir /mnt/ramdisk
  • sudo chown nobody:nogroup /mnt/ramdisk
  • sudo mount -t tmpfs -o size=10240m tmpfs /mnt/ramdisk
  • 若宣告上超出 RAM 實際的大小,是不會造成問題的,但此時硬碟空間也用上了。故量力而為。
  • 若要卸載 sudo umount /mnt/ramdisk
  • 在 ramdisk 中的資料,應可理解只要卸載或關機,就會消失不見。
  • 以下是另一階段,視需要再使用。
  • 若要每次開機都自動掛載,則編輯 /etc/fstab 這份檔案,底下加入一行:
  • tmpfs  /mnt/ramdisk  tmpfs  rw,size=10G  0   0
  • 又在此前提下,我們應是會想要在關機前自動備份 ramdisk 中的所有檔案,那我們就要做一個服務,在開機時將備份資料夾 ramdisk_backup 中的所有檔案複製到 ramdisk,關機前將檔案備份從 ramdisk – > ramdisk_backup:
  • sudo mkdir /mnt/ramdisk_backup
  • 接著建立編輯服務檔,如下段落,注意須把 ken 改成您登入的使用者名稱
  • 而假設有某 this_one.service 相依於需使用該 ramdisk,則需加入 Before=this_one.service,以確保同步及 ramdisk 已 ready。同時必須在 this_one.service 中也加入 After=this_ramdisk.mount 和 Requires=this_ramdisk.mount。其中 this_ramdisk.mount 的名稱由此指令查詢 systemctl list-units –type=mount(注意 – -t。通常是路徑再把反斜線改成 dash,例如 /mnt/rd/,mnt-rd.mount)
  • sudo gedit /lib/systemd/system/ramdisk-sync.service
[Unit]
Description=ramdisk backup service
Before=umount.target this_one.service

[Service]
Type=oneshot
User=root
ExecStartPre=/bin/chown -Rf ken /mnt/ramdisk
ExecStart=/usr/bin/rsync -a /mnt/ramdisk_backup/ /mnt/ramdisk/
ExecStop=/usr/bin/rsync -a --delete /mnt/ramdisk/ /mnt/ramdisk_backup/
ExecStopPost=/bin/chown -Rf ken /mnt/ramdisk_backup
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

rsync

類似 cp 指令,其目的是用於備份檔案,故會有此性質的功能。

  • 指令:rsync <options> <source> <destination>
  • 用法,例如 rsync /tmp/1.txt /home/ken/,把 1.txt 複製到 ken 的家目錄下,而原本 1.txt 的 timestamp 不會被延用在新的 1.txt,其 timestamp 會使用複製當下的時間
  • 參數選項:
  • -z ,啟用壓縮,但並非是壓縮出結果,而是複製過程中做壓縮,以加速複製。建立的目的地檔與來源一樣,並沒有壓縮。
  • -r ,recursive,該指定目錄下的所有(東西)檔案/目錄/子目錄,都會備份到目的地
  • -a ,archive,歸檔封存,其 timestamp 會保留原始的,不會變更成最新的時間,此外,已內俱 -r 的性質故不需加指定 -r,以下為它已內俱的性質:Recursive mode,Preserves symbolic links;即連結檔一樣會被複製,Preserves permissions;即檔案模式會被複製保留著,Preserves timestamp,Preserves owner and group;即保留擁有者名稱。
  • -d,只複製目錄,略過檔案
  • –delete,刪除,若目的有,但來源沒有,則刪除目的該檔。(注意是 – -d)
  • –existing,只複製目的地有的檔案,即若來源有但目的地沒有的,不做複製(- -e)
  • –progress,顯示複製進度(注意是 – -p)
  • -u,update,只更新檔案。即若目的檔比來源新(timestamp),將不會被更新。
  • -v ,verbose,即會顯示複製過程細節,便於讓使用者觀察以防範出錯而不知所措。
  • -e + <shell-keyword>,例如 -e ssh 表示以 ssh shell 做背景登入並 rsync。結束自動登出
  • -i,複製後顯示來源與目的的差異,即有哪些被更動了。結果會以旗標顯示,共有九個點,例如:
  • f 它是檔案
  • s 大小改變
  • t 時間戳記改變
  • o 擁有者改變
  • g 群組改變
  • 來源或目的都可以是遠端的,以 $user@$hostname:$path 來指定,例如:
  • rsync -avz /root/temp/ ken@example.com:/home/ken/temp/
  • 若要走 ssh 通道,則加 -e ssh 指示以 ssh 終端做登入:
  • rsync -avz -e ssh /root/temp/ ken@example.com:/home/ken/temp/
  • 非預設的 port,使用 5900 的話,
  • rsync -avz -e ‘ssh -p 5900’ /root/temp/ ken@example.com:/home/ken/temp/
  • 例子:
  • rsync -zvr /var/opt/installation/inventory/ /root/temp/
  • 壓縮傳輸,顯示細節,並遞迴目錄底下的所有東西,新檔不繼承舊檔的屬性。
  • rsync -zva /var/opt/installation/inventory/ /root/temp/
  • 壓縮傳輸,顯示細節,並遞迴目錄底下的所有東西,舊檔案屬性全被保留到新檔案。
  • 其他:自動化,當某目錄下檔案有變更時,
    連結:https://github.com/lsyncd/lsyncd
    範例:https://www.server-world.info/en/note?os=Ubuntu_16.04&p=lsync

apt

  • apt policy
    列出 repositories
  • add-apt-repository
    加入 ppa
    add-apt-repository ppa:PPA_REPOSITORY_NAME/PPA
    移除 ppa
    add-apt-repository –remove ppa:PPA_REPOSITORY_NAME/PPA (注意- -r)

    例如列出的 repository 中某一行如下,
    http://ppa.launchpad.net/videolan/master-daily/ubuntu bionic/main amd64 Packagesrelease v=18.04,o=LP-PPA-videolan-master-daily,a=bionic,n=bionic,l=VLC Daily Build of master branch,c=main,b=amd64origin ppa.launchpad.net
    則如下下法:
    add-apt-repository –remove ppa:videolan/master-daily(注意- -r)
  • apt update
    更新 repositories 資料庫
  • apt list
    列出所有已知套件
  • apt list –installed(注意 - -i)
    列出已安裝的套件
  • apt install PACKAGE-NAME(s)
    安裝套件
  • apt install –reinstall PACKAGE-NAME(s)(注意 – -)
  • 重新安裝已安裝套件
  • apt upgrade PACKAGE-NAME(s)
    升級套件
  • apt remove PACKAGE-NAME(s)
    移除已安裝的套件
  • cat /var/log/dpkg.log | grep “install.*openssh”(注意雙引號)
    顯示與所指定(此例為 openssh)相關已安裝的套件的安裝時間及名稱
  • ppa 相關的用法
    https://askubuntu.com/questions/307/how-can-ppas-be-removed
  • deb 安裝兩步驟:通常安裝時會有相依性問題而終止,再下第二行指令以修正。
    sudo dpkg -i package_name.deb
    sudo apt -f install
  • apt 部份說明文件
  • 在 /etc/apt/sources.list 中是存放正式的 ubuntu packages lists 連結,可直接修改該檔新增。我們若透過 ppa,或 ubuntu-update ap 加入 list,會新增檔案於 /etc/apt/sources.list.d/ 中;不使用或連結失效可從中直接移除。
  • 加入 sources list 後,apt update,若有 secure issue,disabled by default 的問題,可在該行加入;如下例,
    deb [trusted=yes] http://ppa.launchpad.net/pipewire-debian/pipewire-upstream/ubuntu/ hirsute main
    又或是下 apt update –allow-unauthenticated(注意 – -allow)
  • 執行 apt update,會更新此目錄下的所有檔案,我們可因此作 refresh。如下說明:
    https://unix.stackexchange.com/questions/217369/clear-apt-get-list
  • apt list 的其他疑問連結:
    https://askubuntu.com/questions/58364/whats-the-difference-between-multiverse-universe-restricted-and-main
    https://askubuntu.com/questions/732985/force-update-from-unsigned-repository
    https://askubuntu.com/questions/1373514/can-there-be-any-issue-if-i-edit-sources-list-and-jump-between-ubuntu-releases

Python 不同版本中的切換成 active

  • 先加入 ppa
    sudo add-apt-repository ppa:deadsnakes/ppa
  • 接著安裝其他版本的 python3
  • 顯示當前 active 的 python3
    python3 -V
    python3 –version(注意 - -v)
  • 建立 python3 的所有已安裝版本的切換群組,python3.6 & python3.9
    sudo update-alternatives –install /usr/bin/python3 python3 /usr/bin/python3.6 1(注意 - -i)
    sudo update-alternatives –install /usr/bin/python3 python3 /usr/bin/python3.9 2(注意 - -i)
  • 執行切換
    sudo update-alternatives –config python3(注意 - -c)
  • 檢查版本
  • 最後須注意 Ubuntu 18.04 使用 python3.6 維持系統的運作。切換成更新的版本將造成一些程式或系統運作上的異常,故確定要使用更新的版本請參考以下連結
  • https://python.tutorials24x7.com/blog/how-to-install-python-3-8-on-ubuntu-1804-lts

ssh/scp speed test

抓到了一份 scp 的速度測試,筆者對其內容並非全部了解,但也做了些許雜漫地修改。並不保證其正確性與準確性與參考度。僅供參考。

#!/bin/bash
# scp-speed-test.sh
# Author: Alec Jacobson alecjacobsonATgmailDOTcom
#
# Test ssh connection speed by uploading and then downloading a 10000kB test
# file (optionally user-specified size)
#
# Usage:
#   ./scp-speed-test.sh user@hostname [port [test file size in KB]]
#

ssh_server=$1
test_file="scp-test-file"

# Optional: user specified test file size in kBs
if test -z "$3"
then
  # default block size is 512KB, 10MB
  default_size=10000
  test_size="512"
  count_i=`expr $default_size / 512 + 1`
else
  default_size=$3
  test_size="512"
  count_i=`expr $3 / 512 + 1`
fi


# Optional: user specified port
if test -z "$2"
then
  # default port 22
  test_port="22"
else
  test_port=$2
fi


# generate a 10MB file of all zeros
echo "Generating $default_size kB test file..."

##dd if=/dev/zero of=$test_file bs=$(echo "$test_size*1024" | bc) count=1 &> /dev/null

dd if=/dev/urandom of=$test_file bs="$test_size"K count="$count_i" &> /dev/null


# upload test
echo "Testing upload to $ssh_server..."
up_speed=$(scp -v -P $test_port $test_file $ssh_server:$test_file 2>&1 | \
  grep "Bytes per second" | \
  sed "s/^[^0-9]*\([0-9.]*\)[^0-9]*\([0-9.]*\).*$/\1/g")
up_speed=$(echo "($up_speed*0.0009765625*100.0+0.5)/1*0.01" | bc)

# download test
echo "Testing download from $ssh_server..."
down_speed=$(scp -v -P $test_port $ssh_server:$test_file $test_file 2>&1 | \
  grep "Bytes per second" | \
  sed "s/^[^0-9]*\([0-9.]*\)[^0-9]*\([0-9.]*\).*$/\2/g")
down_speed=$(echo "($down_speed*0.0009765625*100.0+0.5)/1*0.01" | bc)

# clean up
echo "Removing test file on $ssh_server..."
ssh -p $test_port $ssh_server "rm $test_file"
echo "Removing test file locally..."
rm $test_file

# print result
echo ""
echo "Upload speed:   $up_speed kB/s"
echo "Download speed: $down_speed kB/s"

find

查詢廣域 ip

  • wget -qO- http://ipecho.net/plain ; echo
  • https://ifconfig.co/
  • https://www.ez2o.com/App/Net/IP

修復 root 檔案系統

  • 開機時,出現 grub 開機選單時,按 e 進入編輯
  • 在 linux 那一行追加 break=mount
  • 按 F10 重新開機便會進入 initramfs
  • 執行 fsck -f /dev/sdxx
  • 離開
  • 參考

比對兩目錄之內容之異同

  • sudo find ./ -exec stat -c ‘%A %F %g %u %s %Y %n’ {} \; | sort +6 > ~/r1.txt
  • 分別施於兩目錄,再用 diff 比較二輸出檔
  • 通常我們用 cp -rp 來複製出完全相同(含檔案屬性權限)的另一目錄。
  • 不適用於任一檔案本身及其對應,是否全同,其需再利用 checksum。

硬體資訊

  • lshw
  • lspci
  • lspci -xxx
  • dmidecode
  • hwinfo
  • cat /proc/cpuinfo

bash 字串處理

  • set –(注意是雙橫槓 – -)
    將參數列清空。
    set – – vars
    將 vars 映對到參數列。
    參考
  • ${!#}
    命令參數列中最後一個參數。
    參考
表示式含義
${var}變數 var 的值, 與 $var 相同
${var-DEFAULT}如果 var 沒有被宣告, 那麼就以 $DEFAULT 作為其值(var 空值或非空不作處理)
${var+DEFAULT}如果 var 空值或非空, 那麼就以 $DEFAULT 作為其值(沒宣告不作處理)
${var:-DEFAULT}如果 var 沒有被宣告, 或者其值為空, 那麼就以 $DEFAULT 作為其值(非空不作處理)
${var:+DEFAULT}如果 var 非空, 那麼就以 $DEFAULT 作為其值(var 沒宣告或空值不作處理)
${var=DEFAULT}如果 var 沒有被宣告, 那麼就以 $DEFAULT 作為其值, 並賦值給 var
${var:=DEFAULT}如果 var 沒有被宣告, 或者其值為空, 那麼就以 $DEFAULT 作為其值, 並賦值給 var
${var OTHER}如果 var 宣告了, 那麼其值就是 $OTHER, 否則就為 null 字串
${var:OTHER}如果 var 被設定了, 那麼其值就是 $OTHER, 否則就為 null 字串
${var?ERR_MSG}如果 var 沒被宣告, 那麼就列印 $ERR_MSG
${var:?ERR_MSG}如果 var 沒被設定, 那麼就列印 $ERR_MSG
${!varprefix*}匹配之前所有以 varprefix 開頭進行宣告的變數
${!varprefix@}匹配之前所有以 varprefix 開頭進行宣告的變數
${#string}$string 的長度
${string:position}在 $string 中, 從位置 $position 開始提取子串
${string:position:length}在 $string 中, 從位置 $position 開始提取長度為 $length 的子串
$substring 可以是一個正規表示式
${string#substring}從變數 $string 的開頭, 刪除最短匹配 $substring 的子串
${string##substring}從變數 $string 的開頭,刪除最長匹配 $substring 的子串
${string%substring}從變數 $string 的結尾,刪除最短匹配 $substring 的子串
${string%%substring}從變數 $string 的結尾,刪除最長匹配 $substring 的子串
${string/substring/replacement}使用 $replacement, 來代替第一個匹配的 $substring
${string//substring/replacement}使用 $replacement, 代替所有匹配的 $substring
${string/#substring/replacement}如果 $string 的字首匹配 $substring, 那麼就用 $replacement 來代替匹配到的 $substring
${string/%substring/replacement}如果 $string 的字尾匹配 $substring, 那麼就用 $replacement 來代替匹配到的 $substring
轉貼於 https://codertw.com/%E5%89%8D%E7%AB%AF%E9%96%8B%E7%99%BC/393871/

ACL 細部權限設置

多版本共存的入門可參考這篇討論文章

XZ 的一些用法

  • 原則上壓縮效果優於 gzip
  • xz [選項] [檔案]
  • 只適用於單檔壓縮,且會刪除來源檔生成目的檔。所以多檔可搭配 tar 使用。
  • 壓縮層級從 1 至 9,就直接以數字指定之。預設通常為 6。
  • -[number] 壓縮層級
  • -e 再加強壓縮品質,搭配壓縮層級
  • -v verbose
  • -d 解壓縮。解壓縮關聯不到核心數或執行緒數。
  • -z 壓縮,或不指定亦表壓縮
  • -k 保留來源檔
  • -T[number] 使用最多 number 個執行緒,預設為 1;0 的話是指所有核心都可採用。
  • 搭配 tar,參數是 J
  • tar -Jcf abc.tar.xz {files}
  • tar 下,若要指定壓縮層級,或執行緒數,則需使用參數(取代 J)例如 –use-compress-program=’xz -9T2’(注意 – -u)

以他人身份執行命令

  • sudo runuser -l [user_name] -c ‘command’
  • 參考
PHP Code Snippets Powered By : XYZScripts.com