Ubuntu 安裝

安裝

下載 ISO 可至 下載 Ubuntu | Ubuntu 正體中文站 ,安裝時不要更新,按下列安裝:

Continue without updating

  • Install OpenSSH server
    如果要安裝就打勾吧

最後會出現 Cancel update and reboot (奇怪!不是已經選了 Continue without updating)。按下 Cancel update and reboot 後時間沒有比較快,那就等它吧。

安裝系統後,先以 IP 登入主機,建議採用 Windows-Terminal 來連接 linux 主機。安裝 Terminal 後採用 ssh 終端機進入系統來配置。

安裝 ssh,讓其他電腦採用 ssh 登入方便輸入
安裝 ssh (Install OpenSSH server 沒打勾):
sudo apt install ssh -y

Ubuntu 18/20 查看一下 IP:
ip -c a

如位置如下
inet 192.168.1.20/24 brd 172.31.168.254 scope global dynamic ens32

由終端機以 IP 位置登入:
ssh user@192.168.1.20 (1)
1 user 為安裝 Ubuntu 時,輸入的帳號。
root 的預設密碼是什麼?怎麼無法登入?

因為 root 未設定密碼,必須設定密碼才行

可是要怎麼設定?
採用 sudo 設定 root 密碼
sudo passwd root (1)
1 執行時要注意如果 sudo 需要密碼,那麼第一次輸入的密碼是 sudo 的密碼 (輸入目前登入帳戶的密碼), 第二、三次的密碼才是 root 帳戶的密碼。
sudo 免密碼,執行 sudo 第一次都要輸入密碼實在麻煩

使用 sudo 要設定 /etc/sudoers,但建議不要直接編輯該檔案。

編輯 sudoers 執行下列
sudo visudo (1) (2)
1 如果執行出錯改用下列
取得 root「超級使用者 (superuser)」權限:
su

以 root 帳戶執行:
visudo
2 visudo 會採用常用的編輯器 (如 nano),離開編輯器時;若內容有錯誤,它會提示:
>>> /etc/sudoers: syntax error near line 26 <<<
What now?
Options are:
  (e)dit sudoers file again
  e(x)it without saving changes to sudoers file
  (Q)uit and save changes to sudoers file (DANGER!)
在檔案後面加入免密碼的帳戶 (個別帳戶設定)
user ALL=NOPASSWD: ALL(1)
1 本例的帳戶為 user
或者修改 sudo 群組為免密碼
修改
# Allow members of group sudo to execute any command
%sudo   ALL=(ALL:ALL) ALL

變成
# Allow members of group sudo to execute any command
%sudo   ALL=(ALL:ALL) NOPASSWD:ALL

當帳戶沒有 sudo 權限時錯誤訊息為:
<username> is not in the sudoers file. This incident will be reported.

帳戶必須在 sudoers 檔案設定的權限內才能執行 sudo 指令。
  • 個別帳戶設定

  • sudo 群組設定

上述無 sudo 權限的訊息,並非表示「帳戶」一定要以個別帳戶加入 sudoers 之中,將「帳戶」加入至 sudo 群組也能執行 sudo 指令。

列出 sudo 的成員:
grep sudo /etc/group

sudo:x:27:user (1)
1 在安裝 Ubuntu 時輸入 (新) 的帳戶會預設為 sudo 群組的成員。
sudo 群組的相關指令
將帳戶 ubuntu 加入至 sudo 群組:
sudo gpasswd -a ubuntu sudo

將帳戶 ubuntu 移出 sudo 群組:
sudo gpasswd -d ubuntu sudo

帳戶改變 sudo 群組,需要重新登錄才會生效。


sudoers 檔案中有一條規則
root ALL=(ALL:ALL) ALL

表示 root 帳戶能執行 sudo 也能切換至任何帳戶或群組。

  • root ALL=(ALL:ALL) ALL 第 1 個欄位,指明帳戶 (或群組)。

  • root ALL=(ALL:ALL) ALL 第 1 個 ALL,規範「任何主機」能執行。

  • root ALL=(ALL:ALL) ALL 第 2 個 ALL,帳戶可以切換至哪個 (which) 帳戶,ALL 表示「所有帳戶」。

  • root ALL=(ALL:ALL) ALL 第 3 個 ALL,帳戶可以切換至哪個 (which) 群組,ALL 表示「所有群組」。

  • root ALL=(ALL:ALL) ALL 第 4 個 ALL,帳戶可執行哪些命令,ALL 表示「所有命令」,NOPASSWD:ALL 表示執行任何命令都不需要密碼。

語法為:
使用者 可由哪個主機執行=(可成為哪個帳戶:可成為哪個群組) [NOPASSWD:] 可執行哪些命令
sudo 可切換帳戶或群組來執行命令
sudo --help
 -u, --user=user    以指定的帳戶或 ID 執行命令(或編輯檔案)
 -g, --group=group  以指定的群組或 ID 執行命令

sudo 在沒有指定參數時,是切換至 root 的帳戶來執行,使用者只要有 sudo 的權限即可執行命令。

ubuntu ALL= ALL

ubuntu 執行 sudo 只能以 root 身份執行命令,sudo 以其他身份執行,則 (一定) 會詢問密碼,在執行時會出現下列錯誤:

Sorry, user ubuntu is not allowed to execute
ubuntu ALL=(ALL) ALL

ubuntu 能以 user 帳戶身份 (sudo -u user) 來執行,執行群組的身份也是 user。由於沒有「成為哪個群組」的權限,執行 sudo -g user 將會出錯。

ubuntu ALL=(ALL:ALL) ALL

ubuntu 可以用任何身份來執行命令。

以 ubuntu 來測試 sudo 的權限時,除了 ubuntu 沒有在 sudo 的群組之外,也要在注意在虛擬機 /etc/sudoers.d 目錄中的檔案 (如 90-cloud-init-users) 會預設 ubuntu 帳戶的 sudo 權限。
ubuntu ALL=(ALL) NOPASSWD:ALL
剛安裝可採用 dist-upgrade 更新
sudo apt update && sudo apt dist-upgrade -y

執行後下列應該無列表:
sudo apt list --upgradable
檢查時區是否正確
顯示日期的 RFC 格式:
date -R

Mon, 21 Sep 2020 06:33:38 +0000

設定時區:
sudo timedatectl set-timezone Asia/Taipei

如果執行錯誤,採用下列:
sudo dpkg-reconfigure tzdata

選擇 Asia - Taipei。

如果沒有該命令安裝 tzdata
sudo apt install tzdata -y

顯示日期的 RFC 格式:
date -R

Mon, 21 Sep 2020 14:35:32 +0800 (1)
1 +0800 則正確。
配置 .bashrc
先看一下要改什麼
echo $LANG

C.UTF-8 或 en_US.UTF-8

echo $TIME_STYLE

空值
修改 ~/.bashrc 檔案
force_color_prompt=yes (1)

export TIME_STYLE=long-iso (2)
export LANG='en_US.UTF-8' (3)
1 調整 root 終端機提示字元顏色,找出 #force_color_prompt=yes 將註解(#)取消,跟順序有關位置要正確。
其他帳戶也被註解掉了不過卻有提示色。
2 加入本行,設定 ls 顯示檔案的時間格式。
3 預設值如果是 C.UTF-8 (或 en_US.UTF-8) 則不需加入,如 echo $LANG 為空值,則需加入。
套用 ~/.bashrc
source ~/.bashrc

echo $TIME_STYLE
echo $LANG
不提示主要版本更新 (LXC 請忽略本步驟)
sudo nano /etc/update-manager/release-upgrades
/etc/update-manager/release-upgrades 的 Prompt 設為 never
# Prompt=lts
Prompt=never
修改 syslog 日期格式
sudo nano /etc/rsyslog.conf
註消原始格式
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat (1)
1 前面加上 # 即可。
加入下列格式
# 註消原始格式
# $ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
# 加入下列格式
$template CustomFormat,"%$NOW% %TIMESTAMP:8:15% %hostname% %syslogtag% %msg%\n"
$ActionFileDefaultTemplate CustomFormat
Ubuntu 16 rsyslog 有 bug 實際的記錄有下列的錯誤
rsyslogd-3003: invalid or yet-unknown config file command 'KLogPermitNonKernelFacility' - have you forgotten to load a module? ...

KLogPermitNonKernelFacility 是 bug,參閱: command KLogPermitNonKernelFacility is currently not permitted

修正 /etc/rsyslog.conf
# Ubuntu 16 將下列註消
$KLogPermitNonKernelFacility
rsyslog 另一個 bug 是 xconsole 並未在系統之中。
rsyslogd-2039: Could not open output pipe '/dev/xconsole':: No such file or directory ...
修正 Ubuntu 16 xconsole
sudo mknod -m 640 /dev/xconsole c 1 3
sudo chown syslog:adm /dev/xconsole
確定一下修改日期格式的記錄情況。
sudo tail /var/log/syslog
sudo service rsyslog restart
sudo tail /var/log/syslog
VMWare 採用自動安裝修正

更新出錯 The repository 'cdrom://Ubuntu-Server …​ does not have a Release file。

sudo nano /etc/apt/sources.list
deb cdrom 開頭的設定註解掉或刪除 ( Ctrl+K )。
deb cdrom:[Ubuntu-Server ...
再來呢?

配置 samba 方便 Windows 能以 Linux hostname 登入, 安裝 wins 讓 Linux 能 ping Windows hostname

複製(Clone) ubuntu 虛擬機 MAC 地址相同

Netplan 可能會發生為兩台不同機器上的網橋產生相同的 MAC 地址,若新機器以 DHCP 取得則會是相同的 IP。

重建 /etc/machine-id
sudo rm /etc/machine-id
sudo systemd-machine-id-setup
顯示如下訊息
Initializing machine ID from random generator.
sudo reboot now

帳戶及檔案權限

帳戶

新增使用者
無參數會建立使用者的家 (home) 目錄,home 目錄用於儲存該帳戶的資訊,如 登入的參數(.bashrc)、公開密鑰 (.ssh):
sudo adduser ubuntu
不建立 home 目錄,如該用戶不會登入系統,如 www-data 用戶或者 samba 帳戶,則可不建立:
sudo adduser user1 --no-create-home
改變密碼
改變帳戶本身的的密碼
passwd
改變 root 的密碼
sudo passwd root
刪除帳戶
無參數,僅刪除帳號並保留所有檔案。
sudo userdel ubuntu (1)
使用 -r 選項,使用者 home 目錄及系統內的相關的檔案一併移除。
sudo userdel -r ubuntu
檢視 Linux 帳戶
檢視所有使用者
cat /etc/passwd
列出 www-data 帳戶,在安裝系統後已經存在。
grep www-data /etc/passwd
列出帳戶名
cut -d: -f1 /etc/passwd
其他
whoami 檢視自己的使用者名稱
whoami
檢視單個使用者資訊,可得 id 及該帳戶屬於那些群組
id root
檢視登入成功的使用者記錄
last
檢視登入不成功的使用者記錄
sudo lastb
ubuntu 16 sudo 可能出現 /etc/sudoers.d is world writable 是權限不正確對造成的
正確應如下列
$ls -l /etc/sudoers  /etc/sudoers.d /etc/sudoers.d/README -ld
-r--r----- 1 root root  807 2020-11-21 16:37 /etc/sudoers
drwxr-xr-x 2 root root 4096 2023-01-30 13:20 /etc/sudoers.d
-r--r----- 1 root root  958 2019-10-09 13:55 /etc/sudoers.d/README
修正錯誤
sudo chmod 440 /etc/sudoers
sudo chmod 775 /etc/sudoers.d
sudo chmod 440 /etc/sudoers.d/README

群組

使用者 user 加入群組 group
gpasswd -a user group
使用者 user 移出群組 group
gpasswd -d user group
查看 ubuntu 使用者群組
grep ubuntu /etc/group (1)
1 /etc/group 內容格式為 group_name:passwd:GID:user_list,第一欄位:群組名稱,第二欄位:群組密碼,第三欄位:GID,第四欄位:使用者列表,每個使用者之間用 , 逗號分割; 本欄位為空時表示為使用者本身的群組。

檔案權限

chown 改變檔案擁有者 (ownership)

chown [-R] 帳號名稱[:群組名稱] 檔案或目錄
-R : 進行遞迴 (recursive) 即次目錄下的所有檔案都變更。

chown -R www-data:www-data /usr/share/phpmyadmin/tmp
chmod 改變檔案權限 (mode)

chmod xyz 檔案或目錄 [-R]
xyz 可為「數字類型」或「符號類型」。
-R : 進行遞迴 (recursive) 即次目錄下的所有檔案都變更。

Linux 檔案的基本權限就有九個分別是 owner/group/others,三種身份各有自己的 read/write/execute 權限, 檔案的權限字元為 rwxrwxrwx 這九個權限是三組 (三個一組)! 其中,使用數字來代表各個權限,權限數字對照為 r:4 w:2 x:1

755(rwxr-xr-x)

擁有者具備全部權限,其他人只有讀取和執行的權限。

754 (rwxr-xr--)

擁有者具備全部權限,群組只有讀取和執行的權限,其他人只有讀取權限、無執行權、不能讀取目錄。

644 (rw-r--r--)

檔案擁有者具備讀取和寫入權限,其他人為唯讀。 權限中 [r--] 雖然有 r ,但是由於沒有 x 權限,因此其他使用者並不能進入此目錄!

那擁有者能不能進入此目錄?

能進?! 那 Linux 有 ghost (擁有者只有 6,不能進)。

這個目錄不能用了能刪嗎?

不能刪?! 有 ghost (擁有者有 6,能刪)。

但!為什麼要刪?

您是擁有者改成 744 就好。

X@Y
X @ Y

u)ser 擁有者權限
g)roup 群組權限
o)ther 其它帳號權限
a)ll 全部 (即為 ugo)

+ 加入
- 移除
= 指定

r)ead (讀取)
w)rite (寫入)
e)xecute (執行)

設定使用者家目錄,群組及其他無寫入權。
chmod go-w ~/

服務及排程

systemctl

開機啟動
sudo systemctl enable cron
開機不啟動
sudo systemctl disable cron
啟動服務
sudo systemctl start cron
停止服務
sudo systemctl stop cron
重啟服務
sudo systemctl restart cron
顯示服務狀態
systemctl status cron
檢查 (開機) 是否自動啟動服務:
顯示服務狀態:
systemctl status cron

自動啟動:
● cron.service - Regular background program processing daemon
   Loaded: loaded (/lib/systemd/system/cron.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2022-11-30 07:19:42 CST; 2 months 1 days ago

不自動啟動:
● cron.service - Regular background program processing daemon
   Loaded: loaded (/lib/systemd/system/cron.service; disabled; vendor preset: enabled)

查詢所有啟動的服務再過濾:
systemctl list-unit-files --state=enabled | grep cron

cron.service                           enabled

關機指令碼 Shutdown script

建立 myshutdown.sh (習慣把系統服務類放置於 root)
sudo -i
bash -c 'cat > /root/myshutdown.sh' << "EOF"
#!/bin/bash
umount -a -t cifs,nfs -l
EOF

chmod +x /root/myshutdown.sh
exit
建立關機服務
sudo bash -c 'cat > /etc/systemd/system/myshutdown.service' << "EOF"
[Unit]
Description=Shutdown script
DefaultDependencies=no
Before=shutdown.target reboot.target

[Service]
Type=oneshot
ExecStart=/root/myshutdown.sh

[Install]
WantedBy=reboot.target shutdown.target
EOF
啟用及禁用
重新載入服務的配置文件:
sudo systemctl daemon-reload

啟用 myshutdown:
sudo systemctl enable myshutdown

啟用訊息:
Created symlink /etc/systemd/system/reboot.target.wants/myshutdown.service → /etc/systemd/system/myshutdown.service.
Created symlink /etc/systemd/system/shutdown.target.wants/myshutdown.service → /etc/systemd/system/myshutdown.service

禁用 myshutdown:
sudo systemctl disable myshutdown

禁用訊息:
Removed /etc/systemd/system/shutdown.target.wants/myshutdown.service.
Removed /etc/systemd/system/reboot.target.wants/myshutdown.service.

Service

執行 service 命令顯示說明:
service

Usage: service < option > | --status-all | [ service_name [ command | --full-restart ] ]

列出所有安裝的服務:
service --status-all

[ - ]  mysql (1)
[ ? ]  mysqld_multi
[ + ]  networking

列出開機自動啟動的服務:
service --status-all | grep +

列出服務的命令:
service cron

* Usage: /etc/init.d/cron {start|stop|status|restart|reload|force-reload} (2)
1 +: 服務正在執行。
-: 服務已停止。
?: 服務狀態未知。
2 每個服務的命令並不相同,不過一般都會有 start stop status。

service --status-all 為什麼會出現問號

其原因是 服務 回傳字串 usage:,可參考 /usr/sbin/service 的內容, 這表示服務指令碼並沒有實作 status 命令而回傳該服務的命令說明。

0	program is running or service is OK
1	program is dead and /var/run pid file exists
2	program is dead and /var/lock lock file exists
3	program is not running
4	program or service status is unknown

如果按上面,服務指令碼回傳 4,service 是顯示 [ - ] mysqld_multi, 那如何讓它顯示 [ ? ] mysqld_multi 只能回傳字串 usage:

crontab

每項工作的格式有六個欄位

分 時 日 月 週 執行的命令

數字範圍 分(0 ~ 59) 時(0 ~ 23) 日(1 ~ ?) 月(1 ~ 12) 週(0星期天 ~ 6星期六)

前 5 個欄位為時間欄位,除了可輸入數字外,可採用下列特殊的字符

  • * (星號): 表示任何時間。

  • , (逗號): 多個時段,如時程為 3:00 與 6:00 則為 0 3,6 * * * command

  • - (減號): 範圍,如 08:00 至 12:00 間的每小時的 20 分都進行一項工作則為 20 8-12 * * * command

  • /間隔時間: 如每五分鐘進行一次則為 */5 * * * * command

上述語法具彈性,如 */5 表示任何時間 (*) 每間隔 (/) 5,依據時間位置可能為每五分鐘,每五小時,每五天…​。
8-12/2 表示 8 至 12 每間隔 2 跟 8,10,12 相同。

建立測試檔
sudo -i
bash -c 'cat > /root/testCrontab.sh' << "EOF"
#!/bin/bash
date +"%F %T" > /root/testCrontab.txt
EOF

chmod +x /root/testCrontab.sh
exit
測試執行檔
sudo /root/testCrontab.sh
查看內容是是否更新
sudo cat /root/testCrontab.txt
crontab 工作排程依據不同帳戶有不同的工作排程,可採用 root 簡化設置
修改工作排程,使用 crontab -e 可進入常用的編輯器
sudo crontab -e
輸入 (當然是貼上) 下列內容,每一分鐘執行 /root/testCrontab.sh
*/1 * * * * /root/testCrontab.sh
crontab 其它相關
將使用者的 crontab 全部清除
crontab -r
檢查 cron 服務狀態
systemctl status cron
service cron status
crontab 檔案
sudo -i
cat /var/spool/cron/crontabs/root  (1) (2)

crontab -l (1)
exit
1 可以發現這兩者的內容類似。
2 root 工作排程檔為 /var/spool/cron/crontabs/root,
如果有其他使用者排程,可以查看 /var/spool/cron/crontabs。

套件維護

更新
更新套件
sudo apt update && sudo apt upgrade -y

如果提示 The following packages were automatically installed and are no longer required 則 「移除無作用的套件」,或者不需要提示看直接移除。

移除無作用的套件
sudo apt autoremove --purge -y (1)
1 若出現 not empty so not removed
dpkg: warning: while removing linux-modules-4.15.0-112-generic, directory '/lib/modules/4.15.0-112-generic' not empty so not removed

並不需要去處理,因為 dpkg 不會刪除其他套件的檔案,當目錄不為「空」時,並不會移除目錄。
註:不過有時在出現警告後;在執行完成時該目錄已不存在。

dist-upgrade

如果一直提示 packages can be updated,表示系統將 Package 升級時有相依性的問題,而此相依性需要安裝其它新的 Package 或 影響到其它 Package 的相依性,此 Package 就不會被升級會保留下來,發生這樣的現像時,可執行下列得知那些可升級但未被更新的套件。

查看可更新的套件:
sudo apt list --upgradable

或者模擬更新:
apt-get -s upgrade

平時用 apt upgrade 更新,執行 dist-upgrade 選項建議先備份,若為虛擬機那麼省事些 snapshot 即可。

執行 dist-upgrade:
sudo apt dist-upgrade -y

執行後下列應該無列表
sudo apt list --upgradable
command not found
執行命令:
ifconfig

出現錯誤:
-bash: ifconfig: command not found

安裝命令:
sudo apt install ifconfig

出現錯誤:
E: Unable to locate package ifconfig (1)

用 apt-cache search ifconfig 看看是那一個套件:
apt-cache search ifconfig

iproute2 - networking and traffic control tools
net-tools - NET-3 networking toolkit
gnome-nettool - network information tool for GNOME
inetutils-tools - base networking utilities (experimental package)
...

有不少,不知道要裝那一個。好吧!網頁查到都是裝 net-tools。
sudo apt install net-tools -y
1 ifconfig 並非是套件。
查詢已安裝套件
sudo dpkg -l php*
sudo dpkg -l | grep php

apt list --installed | grep php
apt list --installed | grep net-tools
查詢版本 含可安裝及版本
apt-cache showpkg <pkgname>
查詢可安裝的 PHP
apt-cache search --names-only ^php[0-9]+[.]*[0-9]$
執行 apt-get 出錯如下:
E: Could not get lock /var/lib/dpkg/lock-frontend - open (11: Resource temporarily unavailable)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?
解決方式
sudo rm /var/lib/dpkg/lock-frontend
sudo rm /var/lib/dpkg/lock
sudo rm /var/cache/apt/archives/lock
dpkg 參數 -l 問題
列出安裝的 php 套件:
sudo dpkg -l php*

dpkg-query: no packages found matching phpMyAdmin-4.9.5-all-languages.tar.gz (1)

列出目錄中的檔案:
ls

phpMyAdmin-4.9.5-all-languages.tar.gz
1 疑? dpkg 是去找目錄下的檔案! 選項 -l (簡要列出套件),怎麼跟檔案有關? 不知道!
其他
安裝套件:
sudo apt install xinetd net-tools -y

 安裝指定的版本:
sudo apt install pkgname=version -y

移除套件:
sudo apt autoremove <pkgname> -y --purge

套件已經被卸載,但配置文件仍在
列出已安裝套件的指令是 dpkg -l,檢查行首是否有 rc 標示,就能判別該套件是已經被移除但還有配置文件殘留的項目。
dpkg -l | grep ^rc

rc  libapache2-mod-php7.2

移除 rc:
apt autoremove libapache2-mod-php7.2

怎麼沒有作用,因為沒有安裝

刪除所有 rc 標記的 dpkg 套件:
dpkg -l | grep ^rc | cut -d' ' -f3 | sudo xargs dpkg --purge

git clone

列出遠端標籤 (tag)
以 github OpenCC 為例:
git ls-remote --tags https://github.com/BYVoid/OpenCC (1)

...
2ddaffd31f6f9cae776ec2faa4b88d5c45e0d4d6        refs/tags/ver.1.1.4
59cdfe0ac7db87bc3618ccd8943335420fa9ae9b        refs/tags/ver.1.1.5
c3caa5f0221aeaf6ace45b37a608a236272a796c        refs/tags/ver.1.1.6
1 正規要附加 .githttps://github.com/BYVoid/OpenCC.git
下載指定的分支
語法:
git clone [<options>] [--] <repo> [<dir>]

<options> 選項
<repo>    倉庫位置
<dir>     指定複製目錄名稱,不指定時為專案名稱。

複製標籤 ver.1.1.5 至目錄 1.1.5:
git clone --branch ver.1.1.5 --depth 1 https://github.com/BYVoid/OpenCC 1.1.5 (1)
1 --depth 1 只需複製最近的版本。
得知下載分身 (clone) 的標籤
切換至分身目錄:
cd 1.1.5

以 git log 得知標籤:
git log

commit 59cdfe0ac7db87bc3618ccd8943335420fa9ae9b (grafted, HEAD, tag: ver.1.1.5)

以 git tag 得知標籤:
git tag

ver.1.1.5

git branch 無法取得 (因為 --depth 1 的原因):
git branch

* (no branch)

gem (Ruby)

一般安裝 (apt install)

安裝 Ruby:
sudo apt install ruby

顯示 Ruby 的版本:
ruby --version

ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux-gnu]

顯示 gem 的版本:
gem --version

2.7.6

gem 安裝路徑

顯示 gem 環境,執行 gem env 如下(省略跟安裝路徑無關的訊息):
RubyGems Environment:
  - INSTALLATION DIRECTORY: /var/lib/gems/2.5.0
  - USER INSTALLATION DIRECTORY: /home/ubuntu/.gem/ruby/2.5.0
  - GEM PATHS:
     - /var/lib/gems/2.5.0
     - /home/ubuntu/.gem/ruby/2.5.0
  - SHELL PATH:
     - /usr/local/sbin
     - /usr/local/bin
     - /usr/sbin
套件會安裝至兩個目錄
  • 一個是安裝目錄 INSTALLATION DIRECTORY: /var/lib/gems/2.5.0
    註:實際上還再附加 gems,如 /var/lib/gems/2.5.0/gems

  • 另一個是使用者安裝目錄 USER INSTALLATION DIRECTORY: /home/ubuntu/.gem/ruby/2.5.0
    註:跟上述的註解一樣,要附加 gems。

sudo gem install 會安裝至「安裝目錄」,也會在 /usr/local/bin 建立指令檔,由於 gems 是安裝使用者主目錄外,在安裝 gems 時需要以 sudo 執行。


解除安裝 Ruby 前,先解除安裝 gems,因為要刪除指令檔。

gems 解除安裝:
gem uninstall -aIx

-a Uninstall all matching versions
-I Ignore dependency requirements while uninstalling
-x Uninstall applicable executables without confirmation
在執行 uninstall -aIx 時可能會有下列訊息
ERROR:  While executing gem ... (Gem::InstallError)
    minitest is not installed in GEM_HOME, try:
        gem uninstall -i /snap/ruby/284/lib/ruby/gems/2.7.0 minitest
按訊息提示執行
sudo gem uninstall -i /snap/ruby/284/lib/ruby/gems/2.7.0 minitest (1)
1 如果執行出現下列訊息可忽略,/snap/ruby 的目錄會在解除安裝 Ruby (sudo snap remove ruby) 時移除。
ERROR:  While executing gem ... (Gem::FilePermissionError)
    You don't have write permissions for the /snap/ruby/284/lib/ruby/gems/2.7.0 directory.
在解除安裝 Ruby 前先得知安裝目錄
gem env

apt 安裝的結果:
INSTALLATION DIRECTORY: /var/lib/gems/2.7.0
USER INSTALLATION DIRECTORY: /home/ubuntu/.gem/ruby/2.7.0

Snap 安裝的結果:
INSTALLATION DIRECTORY: /home/ubuntu/.gem
USER INSTALLATION DIRECTORY: /home/ubuntu/.gem/ruby/2.7.0
解除安裝 Ruby
apt 解除安裝 ruby:
sudo apt autoremove ruby -y --purge

Snap 解除安裝 ruby:
sudo snap remove ruby
刪除 Ruby 殘留目錄
sudo rm -rf /var/lib/gems
sudo rm -rf /home/*/.gem

安裝 Snap Ruby.

先更新 Ubuntu:
sudo apt-get update && sudo apt-get upgrade -y

再安裝 Snap:
sudo apt install snapd -y

列出 ruby channels:
snap info ruby

3.0/stable:       3.0.5  2022-12-01 (287) 28MB classic
2.7/stable:       2.7.7  2022-12-01 (284) 13MB classic

安裝 Ruby 2.7:
sudo snap install ruby --channel=2.7/stable --classic

重置 bash 記憶程式的路徑:
hash -r

檢查 Ruby 版本:
ruby -v

ruby 2.7.7p221 (2022-11-24 revision 168ec2b1e5) [x86_64-linux]

若要安裝 (刷新) 3.0:
sudo snap refresh ruby --channel=3.0/stable
顯示 gem 環境,執行 gem env 如下(省略跟安裝路徑無關的訊息):
RubyGems Environment:
  - INSTALLATION DIRECTORY: /home/ubuntu/.gem
  - USER INSTALLATION DIRECTORY: /home/ubuntu/.gem/ruby/2.7.0
  - GEM PATHS:
     - /home/ubuntu/.gem
     - /snap/ruby/284/lib/ruby/gems/2.7.0
  - SHELL PATH:
     - /usr/local/sbin
     - /usr/local/bin
     - /usr/sbin
     - /usr/bin
套件會安裝至兩個目錄
  • 一個是安裝目錄 INSTALLATION DIRECTORY: /home/ubuntu/.gem
    註:實際上還再附加 gems,如 /home/ubuntu/.gem/gems

  • 另一個是使用者安裝目錄 USER INSTALLATION DIRECTORY: /home/ubuntu/.gem/ruby/2.7.0
    註:跟上述的註解一樣,要附加 gems。

gem install 會安裝至「安裝目錄」,也會在 ~/.gem/bin 建立指令檔,但該路徑並未在 PATH 中。
安裝的 gems 是在使用者主目錄內,安裝時不需要sudo 執行。

~/.gem/bin 加入 PATH,修改 /etc/environment
修改 /etc/environment:
sudoedit /etc/environment
或
sudo nano /etc/environment

套用 /etc/environment:
. /etc/environment
或
source /etc/environment

gem 常用命令

找出可安裝的套件及版本:
gem search <套件REGEXP> [選項]

「套件REGEXP」表示找出前置合乎「套件名稱」的所有套件,除非加入 -e 選項 (全吻合)。
註:套件名稱不可含版號。

search 有那些可用選項:
gem search -h

-a, --all    顯示 gem 所有版本
-e, --exact  套件名稱全吻合
--prerelease 顯示預先發行版本 (註:可簡化成 --pre)
列出已安裝的套件:
gem list
顯示已安裝的套件的詳細資料:
gem list <套件REGEXP> -d

如詳細資料中顯示
Installed at: /var/lib/gems/2.5.0

實際安裝的路徑是在 /var/lib/gems/2.5.0/gems/套件含版號,如果有更新,會顯示多個版本。
找出套件指令檔路徑:
gem which <套件>

一般情況,套件的指令檔會在套件的安裝路徑之中,套件的「資料」可能在指令檔的上層。多個版本時應採用 which 來得知目前是用那一個版本。
安裝 gem-path,找出套件路徑:
安裝 gem-path 套件:
gem install gem-path

執行 gem-path 得知套件安裝路徑:
gem path <套件>

系統資訊

Linux 版本

得知版本:
lsb_release -a

No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.6 LTS
Release:        16.04
Codename:       xenial

得知版本:
cat /etc/os-release
在 LXC 內是取得 Host 的資訊
得知 Fedora Debian 還是 Ubuntu:
cat /proc/version

檢查 kernel 版本:
uname -r

4.4.0-179-generic

Linux 記憶體

free -m
要將單位轉換成 Bytes, MB 及 GB, 分別是加上 -b, -m 及 -g,預設為 Bytes,-v 顯示版本。

      total used free shared buff/cache available
Mem:   1478  299  152     20       1025       959
Swap:   979    0  979

total: 安裝記憶體容量
used: 已使用憶體容量
free: 未使用記憶體,注意!這裡不是可用記憶體
shared: 共享內存(主要)由 tmpfs 使用
available: 可用記憶體

Linux 行程

top

top - 08:15:01 up 44 min,  1 user,  load average: 0.03, 0.11, 0.10 (1)
Tasks:  63 total,   1 running,  62 sleeping,   0 stopped,   0 zombie (2)
%Cpu(s):  1.5 us,  0.4 sy,  0.0 ni,100.0 id,  0.3 wa,  0.0 hi,  0.1 si,  0.0 st (3)
KiB Mem :  1741400 total,  1600560 free,    73184 used,    67656 buff/cache (4)
KiB Swap:        0 total,        0 free,        0 used.  1557120 avail Mem (5)

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND (6)
    1 root      20   0   56816   6548   5264 S  0.0  0.4   0:00.95 systemd
    2 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kthreadd
    3 root      20   0       0      0      0 S  0.0  0.0   0:00.02 ksoftirqd/0
1 top - 08:15:01 up 44 min, 1 user
08:15:01:目前時間。up 44 min:主機開機時間。1 user:目前登入系統使用者數。
load average: 0.03, 0.11, 0.10
系統每 1 分鐘、5 分鐘、15 分鐘的負載情況,load average 資料是每隔 5 秒鐘檢查一次行程, 按特定演算法計算出數值。當數字除以邏輯 CPU 數,結果高於 5 則表示系統已超負荷運轉。
2 Tasks: 63 total, 1 running, 62 sleeping, 0 stopped, 0 zombie
目前系統共 63 個行程,1 個正在執行 (running),62 個休眠 (sleeping),0 個已停止 (stopped),0 個僵屍狀態 (zombie)。
3 %Cpu(s): 1.5 us, 0.4 sy, 0.0 ni,100.0 id, 0.3 wa, 0.1 hi, 0.1 si, 0.0 st
1.5 us:用戶佔用 CPU 百分比。
0.4 sy:核心佔用 CPU 百分比。
0.0 ni:改變過優先順序的行程佔用 CPU 百分比。
0.3 wa:IO 等待佔用 CPU 百分比。
0.1 hi:硬體中斷(Hardware IRQ)佔用 CPU 百分比。
0.0 si:軟體中斷(Software Interrupts)佔用 CPU 百分比。
4 KiB Mem: 1741400 total, 1600560 free, 73184 used, 67656 buff/cach
記憶體使用狀態:
1741400 total:實體記憶體容量
1600560 free:剩餘記憶體容量
73184 used:已使用的記憶體容量
67656 buff/cach:暫存記憶體容量
5 KiB Swap: 0 total, 0 free, 0 used. 1557120 avail Mem
swap 使用狀態:
0 total:swap 總容量
0 free:已使用的 swap 容量
0 used:剩餘 swap 容量
1557120 avail Mem 暫存記憶體容量
6 PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
行程現況: PID:行程 id(Process ID)
USER:該行程使用者
PR:行程優先順序
NI:nice值 (值越小優先權優高)
VIRT:該行程使用的虛擬記憶體總量,單位 kb(VIRT=SWAP+RES)
RES:該行程程使用的、未被使用的實體記憶體大小,單位 kb(RES=CODE+DATA)
SHR:共用記憶體大小 (單位kb)
S:行程狀態。D=不可中斷的睡眠狀態 R=運行 S=睡眠 T=跟蹤/停止 Z=僵屍進程
%CPU:上次更新到現在的CPU時間佔用百分比
%MEM:行程使用的實體記憶體百分比
TIME+:行程使用的CPU時間總計,單位 1/100 秒
COMMAND:行程名稱
top 常用參數

b: Batch mode,更新時產生整個畫面,以便用於記錄。
d: 指定更新時間(單位:秒)。
o: 指定要輸出的欄位名稱。
p: 指定要觀察的 pid。
u: 指定要觀察的使用者名稱。

使用 batch mode,觀察 pid 6164 的行程並每 2 秒更新一次
top -b -d 2 -p 6164 +

其中 -b 參數是 batch 模式的意思,而 -o 參數則是以 %MEM (記憶體用量) 排序,

top -b -o %MEM | head -n 17

head -n 17 則是篩選輸出前 17 行。

觀察使用者 www-data 所執行的行程並每 2 秒更新一次
top -d 2 -u www-data

top 顯示成 MB

e
Change the scaling factor on the summary display

Shift+e
Change the scaling factor on the task

Shift+w
Save current settings

ps kill

查詢 ps 的命令說明,若執行 ps -help 得到的說明並無作用,只在 man ps 有完整說明。

a         顯示所有行程 (預設是當前使用者的行程)
u         顯示行程的使用者
x         顯示未附加到終端的行程
-e, -A    顯示所有行程
-l        長格式,顯示完整的欄位。註:不能跟 u 合併使用。
ps 示例
ps aux | grep php
ps -e -l | grep php
kill 刪除行程,若要強制結束可使用 -9 參數
kill PID -9
killall 行程名稱,將同名稱的行程一次刪除。
killall 行程名稱

Ubuntu 筆記

journalctl

測試 journalctl 時間格式
journalctl --help
-o --output=STRING Change journal output mode (short, short-precise,
                     short-iso, short-iso-precise, short-full,
                     short-monotonic, short-unix, verbose, export,
                     json, json-pretty, json-sse, cat)

sudo journalctl -n 1 -o short
Jan 30 21:56:12

sudo journalctl -n 1 -o short-precise
Jan 30 21:56:31.128574

sudo journalctl -n 1 -o short-iso-precise
2023-01-30T21:57:16.638238+0800

sudo journalctl -n 1 -o short-iso
2023-01-30T21:56:46+0800

sudo journalctl -n 1 -o short-iso-precise
2023-01-30T21:57:16.651012+0800

sudo journalctl -n 1 -o short-full
Mon 2023-01-30 21:57:55

sudo journalctl -n 1 -o short-monotonic
[370817.508650]

sudo journalctl -n 1 -o short-unix
1675087118.807346

Ubuntu 18.04 昇級至 20.04

步驟如下:

  1. 備份或虛擬機快照

  2. 更新 Ubuntu 18.04 LTS 所有已安裝的套件

    sudo apt update && sudo apt upgrade -y
    sudo reboot
  3. 刪除所有未使用的舊套件

    sudo apt autoremove --purge -y
  4. 安裝 update-manager-core

    sudo apt install update-manager-core -y
  5. 將 Ubuntu 18.04 LTS 升級到 20.04 LTS

    sudo do-release-upgrade -q
    do-release-upgrad 說明:
    do-release-upgrade --help
    
    -d, --devel-release  昇級至開發版本
    -q, --quiet
    ...
    Some third party entries in your sources.list were disabled. You can
    re-enable them after the upgrade with the 'software-properties' tool
    or your package manager.
    
    To continue please press [ENTER] (按下 Enter)
    
    ...
    Installing the upgrade can take several hours. Once the download has
    finished, the process cannot be canceled.
    
     Continue [yN]  Details [d] (輸入 y)
    
    ...
    Restart services during package upgrades without asking?
    <Yes> (選取 <Yes>)
    
    Configuration file '/etc/rsyslog.conf'
     ==> Modified (by you or by a script) since installation.
     ==> Package distributor has shipped an updated version.
       What would you like to do about it ?  Your options are:
        Y or I  : install the package maintainer's version
        N or O  : keep your currently-installed version
    *** rsyslog.conf (Y/I/N/O/D/Z) [default=N] ? (按下 Enter)
    ...
    Samba server and utilities
    What do you want to do about modified configuration file smb.conf?
    keep the local version currently installed (選取本選項)
    
    ...
    Configuring openssh-server
    What do you want to do about modified configuration file sshd_config?
    keep the local version currently installed (選取本選項)
    
    ...
    460 packages are going to be removed.
    Removing the packages can take several hours.
     Continue [yN]  Details [d] (輸入 y)
    
    ...
    To finish the upgrade, a restart is required.
    If you select 'y' the system will be restarted.
     Continue [yN] (輸入 y)