Skip to main content

Linux Basic Notes

Linux Boot System

Grub

Grub Configuration

  • /etc/default/grub配置文件, 用于一些基本的修改项, 如默认启动项, Grub 界面等待时长, Grub 主题 etc. More details in info -f grub -n 'Simple configuration'
# Default Startup OS
GRUB_DEFAULT=0

# Default Timeout
GRUB_TIMEOUT=5

# https://github.com/vinceliuice/grub2-themes
GRUB_THEME="/boot/grub/themes/Tela/theme.txt"
  • /etc/grub.d/*生成/boot/grub/grub.cfg的执行脚本(update-grub命令), 可以更细致地修改启动项, 如各个启动项的名称、顺序等.

Grub Repair

Windows Repair
  • easyBCD for non-efi loader
  • with efi loader, run command:
# root commander
bcdedit /set "{bootmgr}" path \EFI\ubuntu\grubx64.efi
Ubuntu Live Repair
sudo add-apt add-apt-repository ppa:yannubuntu/boot-repair
sudo apt update
sudo apt install boot-repair
boot-repair

重装 Linux

  • 自动挂载项 /etc/fstab etc/rc.local
  • 自定义脚本-新建目录(加入环境变量)
  • 自定义别名 ~/.bashrc

SSH Commands

Key

ssh-keygen -t rsa
ssh-add ~/.ssh/id_rsa

SSHD

  • config file in /etc/ssh/sshd_config
sudo systemctl reload sshd
sudo service restart sshd

SSH Config File

~/.ssh/config:

  • Host 别名
    • HostName 主机名(ip) ssh user@ip
    • Port 可忽略
    • User 登录用户名 ssh user@ip
    • PreferredAuthentications publicKey
    • IdentityFile 密钥文件完整路径 ssh -i file
Host github.com
HostName github.com
PreferredAuthentications publicKey
IdentityFile ~/.ssh/id_rsa
Host cs.github.com
HostName github.com
PreferredAuthentications publicKey
IdentityFile ~/.ssh/cs
Host cloud
HostName xx.org
User root
IdentityFile ~/.ssh/dsl_private_key
Host bwg
HostName 23.106.150.152
User root
Port 29692
git clone git@github.com:user/repo
git clone git@cs.github.com:user/repo
ssh -qTfnN -D 7070 bwg
google-chrome socks5 127.0.0.1 7070

密钥文件

  • 登录远程主机:ssh -i sabertaz root@119.29.140.60
  • 文件传输:sftp -i sabertaz root@119.29.140.60
  • 登录数据库:mysql -h 10.66.135.125 -P 3306 -u root -p

远程传输文件

rsync -ax -e 'ssh -c blowfish' /root/start_dir root@x.x.x.x:/root/dest_dir
sshpass -p "$DEPLOY_PASSWORD" \
scp -o StrictHostKeyChecking=no \
-P $DEPLOY_PORT \
-r ./build $DEPLOY_USER@$DEPLOY_ADDR:/var/www/html

命令优先级

  1. 包含路径命令 ./vmtools.pl.
  2. 别名命令.
  3. Bash 内部命令.
  4. $PATH 包含目录内的命令 (/bin//sbin).

Linux Folder Structure

man hier

通过源码包安装的软件,可以通过 ./configure --prefix=/opt/.

  • /usr/src: Kernel source code.
  • /usr/share/applications: Desktop shortcuts.
  • /usr/share/fonts/opentype: Open Type Fonts (OTF).
  • /usr/share/fonts/truetype: True Type Fonts (TTF).
  • /etc/nginx: Nginx.

Ubuntu

Ubuntu Locale Settings

export LANG=en_US
xdg-user-dirs-gtk-update
export LANG=zh_CN
  • /var/lib/locales/supported.d/local
sudo locale-gen zh_CN.GBK
sudo locale-gen zh_CN.GB18030
sudo dpkg-reconfigure locales

Ubuntu Themes

Icon Themes

Nightly build for Numix Circle icon:

sudo add-apt-repository ppa:numix/ppa
sudo apt update
sudo apt install numix-icon-theme-circle

GTK Themes

GTK/GNOME themes located in /usr/share/themes/ or ~/.themes/:

# Vimix Cursors Installation
git clone https://github.com/vinceliuice/Vimix-cursors
sudo ./Vimix-cursors/install.sh

# WhiteSur GNOME theme Installation
git clone https://github.com/vinceliuice/WhiteSur-gtk-theme
sudo ./WhiteSur-gtk-theme/install.sh -t all -i ubuntu
# Tweak for Firefox
sudo ./WhiteSur-gtk-theme/tweaks.sh -f
# Tweak for Snap Apps
sudo ./WhiteSur-gtk-theme/tweaks.sh -s
# Tweak for GDM
sudo ./WhiteSur-gtk-theme/tweaks.sh -g -i ubuntu
# Tweak Help Docs
sudo ./WhiteSur-gtk-theme/tweaks.sh -h

Repair for not detected HDMI problem:

sudo dpkg-reconfigure gdm3
sudo apt install --reinstall gdm3 lightdm ubuntu-desktop

GNOME Shell Extension

  • Install GNOME shell extension for browser.
  • Install local binding app: sudo apt install chrome-gnome-shell.
  • Visit extensions.gnome.org to install extensions.

Ubuntu Fonts

mkdir -p ~/.local/share/fonts/
cp -fr code-fonts ~/.local/share/fonts/
fc-cache -f -v
fc-list
fc-list : family | sort | uniq

Arch Linux

Setup Arch Linux Configuration

less /usr/share/aif/docs/official_installation_guide_en
pacman -S lynx arch-wiki-docs arch-wiki-lite
lynx /usr/share/doc/arch-wiki/html/index.html
systemctl enable dhcpcd
reboot
pacman -S --needed base-devel git wget jshon expac yajl zsh vim
  • makepkg
curl -L -O https://aur.archlinux.org/cgit/aur.git/snapshot/package_name.tar.gz
cd package_name
less PKGBUILD
less package_name.install

makepkg -si
# -s sync deps
# -i install
# -r rm deps
# -c clean up

Pacman

  • /etc/pacman.conf
  • /etc/pacman.d/mirrorlist

AUR

# packages' list
wget https://aur.archlinux.org/packages.gz

WSL

WSL Installation

Upgrade to WSL 2:

# <!-- markdownlint-disable-next-line MD013 -->
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

# Restart computer.

wget https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi
wsl --set-default-version 2
wsl --set-version Ubuntu-22.04 2
wsl -l -v

WSL Proxy Connection

Proxy for WSL 2:

HostIP=$(cat /etc/resolv.conf | grep nameserver | awk '{ print $2 }')
WslIP=$(hostname -I | awk '{print $1}')
Port=1080
PROXY_SOCKS="socks5://${HostIP}:${Port}"

# For Git CLI.
git config --global http.proxy "${PROXY_SOCKS}"
git config --global https.proxy "${PROXY_SOCKS}"

# For GitHub CLI.
export HTTP_PROXY="${PROXY_SOCKS}"
export HTTPS_PROXY="${PROXY_SOCKS}"
Socks Client

主机代理客户端需要允许 VLAN (或其他网络) 设备访问本地代理连接.

WSL Remote Connection

Gzip for WSL 2:

echo -en '\x10' | sudo dd of=/usr/bin/gzip count=1 bs=1 conv=notrunc seek=$((0x189))

Network for WSL 2:

netsh winsock reset

WSL Wi-Fi Connection

Win 11 MediaTek Wi-Fi 6 delay start: set Network Connections and WLAN AutoConfig to auto-start in services.

Basic Commands

ls

  • -lh: long human.
  • -ld: long directory.
  • -i inode --color==auto

权限 (user/group/other) 引用计数 user group 文件大小 文件修改时间 文件名.

cd

  • -: 上次目录.
  • ..: 上级目录.

pwd

print working directory

rm

  • –r delete directory
  • –f delete forcedly
  • -i 显示确认信息

cp

  • -r copy directory
  • -p copy property
  • -d copy link
  • -a --all(-pdr)
  • -i 显示确认信息

mv

无需参数(改名+移动)

  • -i 显示确认信息

ln

link: create .bak/.hard (硬链接) and .soft (软链接:创建链接时填写绝对路径).

  • A hard link always points a filename to data on a storage device.
  • A soft link always points a filename to another filename, which then points to information on a storage device.
ln [源文件] [New Hard Link File]
ln -s [源文件] [New Soft Link File]

history

  • -c 清除历史命令
  • -w (~/.bash_history) 保存历史命令

/etc/profile 中修改 HISTSIZE !n/!!/!字符串 重复执行第 n 条/上一条/指定开头的历史命令

# repeat history command
!number

Ctrl R History

Press ctrl-r 提示符改变, 显示我们正在执行反向增量搜索. 搜索过程是反向的,因为我们按照从现在过去某个时间段的顺序来搜寻. 下一步, 我们开始输入要查找的文本搜索返回我们需要的结果. (enter to execute, ctrl-j to copy)

History Shortcuts

commandfunction
Ctrl-p移动到上一个历史条目
Ctrl-n移动到下一个历史条目
Alt-<移动到历史列表开头
Alt->移动到历史列表结尾
Ctrl-r反向增量搜索
Alt-p反向搜索,非增量搜索
Alt-n向前搜索,非增量
Ctrl-o执行历史列表中的当前项,并移到下一个

Time

date

Change ntp (Network Time Protocol) time:

sudo apt-get install ntpdate
sudo iptables -A OUTPUT -p udp --dport 123 -j ACCEPT
sudo iptables -A INPUT -p udp --sport 123 -j ACCEPT
sudo ntpdate time.windows.com
sudo hwclock --localtime --systohc

Use local time (not UTC time):

sudo timedatectl set-local-rtc 1

Find and Search Commands

Locate

结合 updatedb 命令 (该命令一般自动 1 天/次).

Type

Indicate how a command name is interpreted.

Apropos

Display a list of appropriate commands.

Whereis and Whatis

Which

Find

find [搜索路径] [可选参数] [文件名](可加""):

  • -name.
  • -iname: 不区分大小写.
  • -user: user_name 按照所有者搜索.
  • -nouser: 搜索没有所有者的文件.
  • -atime(文件访问时间)/-ctime(改变文件属性)/-mtime(改变文件内容): -10(十天内)/10(十天当天)/+10(十天前).
  • -size: 文件大小, -25k(小于 25k)/25M(25M)/+25G(大于 25G).
  • -inum: inode_number.
  • -a/-o: 逻辑与/逻辑或 (左右两端搜索条件).
  • -exec system_command_list {} ;: 对搜索结果执行操作.
  • -ok system_command_list {} ;: 对搜索结果执行操作.
find . -name "*.bak" -type f
find . -name "*.bak" -type f -delete

Grep

grep [可选参数] '字符串' 文件名:

  • -I: 不区分大小写
  • -v: 排除指定字符串
  • -r: recursive on directory
  • -l: only print matched filename
  • --exclude

Find FunctionalComponent in files and open them all:

grep -lr FunctionalComponent src --exclude=*.md | xargs code

CPU and Process Commands

uptime

Average load information

ps

Report a snapshot of current processes

ps aux

top

top/htop:

  • Display tasks
  • Average load
  • Process status
  • CPU usage

atop:

  • Memory usage
  • Disk I/O usage
  • Network usage

vmstat

Outputs a snapshot of system resource usage:

  • CPU usage
  • Context switch times
  • Interrupt times (/proc/interrupts)
  • Running and exclusive process status
  • Memory usage
  • Swap space
  • Disk I/O usage

pidstat

Process and Thread:

  • CPU usage
  • Context switch times
  • Interrupt times (/proc/interrupts)
pidstat 1

mpstat

  • CPU usage
  • Software interrupt times (/proc/interrupts)
mpstat -P ALL 1

lscpu

Show /proc/cpuinfo.

jobs

list active jobs

bg

place a job in the background

fg

place a job in the foreground

kill

send a signal to a process

killall

kill processes by name

shutdown

shutdown or reboot the system

pstree

outputs a process list arranged in a tree-like pattern

xload and tload

draws a graph showing system load over time

screen

screen -S screenName
screen -ls
screen -r
  • Ctrl+d // detach window
  • Ctrl+k // kill window

CLI Input Output Commands

cat

concatenate files

sort

sort lines of text

uniq

report or omit repeated lines

wc

print newline, word, and byte counts for each file

Head and Tail

output the first/last part of a file

head -n 5 filename
tail -f filename

Tee

read from standard input and write to standard output and files

[me@linuxBox ~]$ ls /usr/bin | tee ls.txt | grep zip
bunzip2
bzip2
....

nl

number lines

fold

wrap each line to a specified length

fmt

a simple text formatter

pr

prepare text for printing

printf

format and print data

Helper and Documentation Commands

Man

  • -f 显示操作等级
  • -k 包含匹配
  • -1/2/.../9 显示命令不同操作等级的帮助
  1. Commands (Programs) Those commands that can be executed by the user from within a shell.
  2. System calls Those functions which must be performed by the kernel.
  3. Library calls Most of the libc functions.
  4. Special files (devices) Files found in /dev.
  5. File formats and conventions The format for /etc/passwd and other human-readable files.
  6. Games
  7. Conventions and miscellaneous Overviews of various topics, conventions and protocols, character set standards, and miscellaneous other things.
  8. System management commands Commands like mount(8), many of which only root can execute.

Help Shell

显示 shell 内部命令帮助,如 cd 命令(shell 内部命令)

Info

显示大型帮助文档 - enter 进入 u 返回 p 上一节 n 下一节 q 退出

System Info

sudo add-apt-repository ppa:dawidd0811/neofetch
sudo apt-get update
sudo apt-get install neofetch
sudo apt-get install screenfetch

Linux Documentation Reference

Compress and Extract Commands

Zip

  • zip -r(目录) 压缩文件 源文件/源目录.
  • unzip 源文件 -d 指定路径.
zip -r archive_name.zip folder_to_compress
unzip archive_name.zip

zipinfo archive_name.zip
unzip -l archive_name.zip

Gz

  • gzip 源文件.
  • gzip –c 源文件 > 压缩文件.
  • gzip -r 源目录 将源目录下所有子文件分别单独压缩.
  • gzip –d(解压缩) 文件.
  • gunzip 压缩文件.

Bz2

不可压缩目录:

  • bzip2 –k(保留源文件) 源文件.
  • bzip2 –d(解压缩) –k(保留压缩文件) 压缩文件.
  • bunzip2 –k(保留压缩文件) 压缩文件.

Tar

.tar.gz/.tar.bz2:

tar [可选参数] 压缩文件(可指定压缩路径) [-c 解压缩路径]源文件/源目录:

  • -z: 将 .tar 压缩为 .tar.gz.
  • -j: 将 .tar 压缩为 .tar.bz2.
  • -c: 打包 -x 解打包.
  • -t: 查看压缩文件.
  • -v: 显示过程.
  • -f: 指定压缩文件名.
  • -C: 指定解压缩路径.
  • -zcvf/-zxvf/-ztcf.
  • -jcvf/-jxvf/-jtvf.

7z

  • a: add.
  • x: extract.
  • -r: recursive.
  • -o: specific path.
  • -t: type.
7z x manager.7z -r -o /home/xx
7z a -t7z -r manager.7z /home/manager/*

UnAr

Decompress files of any format:

unar archive_name.zip
unar archive_name.7z
unar archive_name.rar
unar archive_name.ISO
unar archive_name.tar.gz

LsAr

Peek files in a compress file of any format:

lsar -l archive_name.zip
lsar -l archive_name.7z
lsar -l archive_name.ISO
lsar -l archive_name.rar
lsar -l archive_name.tar.gz

User and Group Commands

  • w/who 查看用户详细信息
  • last 显示所有用户登陆信息(/var/log/wtmp)
  • lastlog 显示所有用户最后一次登陆时间(/var/log/lastlog)

组操作

创建组

groupadd test

修改组

groupmod -n test2 test -g

删除组

groupdel test2

查看组

  • groups someUser
  • cat /etc/group
cat /etc/passwd | awk -F [:] ‘{print $4}’
\ |sort|uniq | getent group |awk -F [:] ‘{print $1}’

/etc/passwd is a configuration file which stores user account information. It is a plain text-based file containing information like username, user ID and group ID.

用户操作

增加用户

useradd [options] LOGIN

Options:

  • -b, --base-dir BASE_DIR 设置基本路径作为用户的登录目录
  • -c, --comment COMMENT 对用户的注释
  • -d, --home-dir HOME_DIR 设置用户的登录目录
  • -D, --defaults 改变设置
  • -e, --expiredate EXPIRE_DATE 设置用户的有效期
  • -f, --inactive INACTIVE 用户过期后,让密码无效
  • -g, --gid GROUP 使用户只属于某个组
  • -G, --groups GROUPS 使用户加入某个组(附设组)
  • -h, --help 帮助
  • -k, --skel SKEL_DIR 指定其他的 skel 目录
  • -K, --key KEY=VALUE 覆盖 /etc/login.defs 配置文件
  • -m, --create-home 自动创建登录目录
  • -l, 不把用户加入到 lastlog 文件中
  • -M, 不自动创建登录目录
  • -r, 建立系统账号
  • -o, --non-unique 允许用户拥有相同的 UID
  • -p, --password PASSWORD 为新用户使用加密密码
  • -s, --shell SHELL 登录时候的 shell
  • -u, --uid UID 为新用户指定一个 UID
  • -Z, --selinux-user SEUSER use a specific SEUSER for the SELinux user mapping
useradd -s bash -m testUser
passwd testUser # modify `/etc/passwd`, then add to `/etc/sudoers`

adduser is a perl script which uses useradd binary in back-end, adduser is more user friendly and interactive.

修改用户

usermod -d /home/test -G test2 test

  • -l 新用户名 旧用户名 修改用户名
  • -g 新用户组 目标用户 改变用户所属组

gpasswd -a test test2 将用户 test 加入到 test2 组(附设组)

gpasswd -d test test2 将用户 test 从 test2 组中移出

usermod -aG sudo <username>

删除用户

userdel test -r 同时删除用户登录目录(/home/xxx)

查看用户

w/who 查看当前登录的所有用户

whoami 查看当前登录用户名

finger apacheUser 查看单个用户信息

限制用户

  • passwd -l 用户名 锁定用户
  • passwd -u 用户名 解锁用户
  • passwd -d 用户名 清除用户密码

Privilege Management Commands

Common Privilege Management

  • chown 用户名:组名 文件名
  • chgrp 组名 文件名
  • umask 存储位置 ——/etc/profile
  • 文件默认权限 = 文件默认最大权限 rw-(666) 减去 umask 值(如----w--w-)(022)
  • 目录默认权限 = 目录默认最大权限 rwx(777) 减去 umask 值
  • id <username>

ACL Privilege Management

  • 查看分区 ACL 权限是否开启 dumpe2fs -h 设备分区名

  • 临时开启分区 ACL 权限 mount -o remount,acl 设备分区名

  • 永久开启分区 ACL 权限 /etc/fstab

  • setfacl -m (d:默认权限) u/g:用户名/组名:权限(rwx) 文件名

  • getfacl 文件名——查看文件 ACL 权限

Sudo Privilege Management

/etc/sudoers.tmp

SetUID and SetGID

可执行程序/目录+普通用户临时获得 root 权限 (rws):

  • chmod 0xxx 取消双权限
  • chmod 2xxx 设置 SetGID 权限
  • chmod 4xxx 设置 SetUID 权限
  • chmod 6xxx 设置双权限

Disk IO Commands

主分区 (primary) 与延伸分区 (extended) 延伸分区可以继续划分成逻辑分区 (logical).

挂载命令

mount [-t 文件系统][-o 特殊选项] 设备文件名 挂载点(挂载目录/media /misc /mnt)
  • 无参数: 显示当前挂载设备.
  • -a: 依据 /etc/fstab 文件配置, 自动挂载.
umount 设备文件名/挂载点
fdisk –l

修复命令

sudo debugfs /dev/sda9
> debugfs: lsdel

分区命令

fdisk

分区表类型 MBR

n p e l 新 主 逻辑 扩展 分区 w 激活

parted

分区表类型 MBR/GPT

  • mklabel 选择分区表类型
  • print 打印分区信息
  • mkpart 新建分区
  • rm 删除分区
  • unit 选择单位
  • quit 结束分区

Zero Copy

  • read + write: 4 context switch, 4 data copy (2 DMA, 2 CPU).
  • mmap + write: 4 context switch, 3 data copy (2 DMA, 1 CPU).
  • sendfile: 2 context switch, 3 data copy (2 DMA, 1 CPU).
  • scatter and gather sendfile: 2 context switch, 2 data copy (1 DMA, 1 SG-DMA).
  • 传输大文件 (无法命中内核 PageCache) 使用 异步 I/O + 直接 I/O, 传输小文件使用 Zero Copy.
location /video/ {
sendfile on;
aio on;
directio 1024m;
}

Device Management Commands

Host System Info Commands

#!/bin/bash

# Simple print cpu topology

# numactl --hardware
# ls /sys/devices/system/node/node0
# lscpu

function get_nr_processor()
{
grep '^processor' /proc/cpuinfo | wc -l
}

function get_nr_socket()
{
grep 'physical id' /proc/cpuinfo | awk -F: '{
print $2 | "sort -un"}' | wc -l
}

function get_nr_siblings()
{
grep 'siblings' /proc/cpuinfo | awk -F: '{
print $2 | "sort -un"}'
}

function get_nr_cores_of_socket()
{
grep 'cpu cores' /proc/cpuinfo | awk -F: '{
print $2 | "sort -un"}'
}

echo '===== CPU Topology Table ====='
echo

echo '+--------------+---------+-----------+'
echo '| Processor ID | Core ID | Socket ID |'
echo '+--------------+---------+-----------+'

while read line; do
if [ -z "$line" ]; then
printf '| %-12s | %-7s | %-9s |\n' $p_id $c_id $s_id
echo '+--------------+---------+-----------+'
continue
fi

if echo "$line" | grep -q "^processor"; then
p_id=`echo "$line" | awk -F: '{print $2}' | tr -d ' '`
fi

if echo "$line" | grep -q "^core id"; then
c_id=`echo "$line" | awk -F: '{print $2}' | tr -d ' '`
fi

if echo "$line" | grep -q "^physical id"; then
s_id=`echo "$line" | awk -F: '{print $2}' | tr -d ' '`
fi
done < /proc/cpuinfo

echo

awk -F: '{
if ($1 ~ /processor/) {
gsub(/ /,"",$2);
p_id=$2;
} else if ($1 ~ /physical id/){
gsub(/ /,"",$2);
s_id=$2;
arr[s_id]=arr[s_id] " " p_id
}
}

END{
for (i in arr)
printf "Socket %s:%s\n", i, arr[i];
}' /proc/cpuinfo

echo
echo '===== CPU Info Summary ====='
echo

nr_processor=`get_nr_processor`
echo "Logical processors: $nr_processor"

nr_socket=`get_nr_socket`
echo "Physical socket: $nr_socket"

nr_siblings=`get_nr_siblings`
echo "Siblings in one socket: $nr_siblings"

nr_cores=`get_nr_cores_of_socket`
echo "Cores in one socket: $nr_cores"

let nr_cores*=nr_socket
echo "Cores in total: $nr_cores"

if [ "$nr_cores" = "$nr_processor" ]; then
echo "Hyper-Threading: off"
else
echo "Hyper-Threading: on"
fi

echo
echo '===== END ====='

Screen Monitor Commands

xrandr

xrandr -s 1920x1800 # set resolution

Monitor Info

sudo apt-get install read-edid
sudo get-edid | parse-edid

Touch Pad Synoptics

synclient TouchpadOff=0

Package Manager Commands

RPM Commands

安装和卸载时同时存在依赖性(包依赖、库依赖)

rpm 查询:

  • -q 包名 查询已安装的包 //必备参数
  • -a 查询所有已安装的包
  • -i 查询软件信息
  • -l list
  • -f 查询系统文件属于哪个软件包
  • -R 查询软件包的依赖性
  • -p 查询未安装包 //普适参数

rpm 校验(查看 Cracker 信息):

  • -V 校验已安装包 相应信息不是.号便是被修改项 可用于找回丢失的系统命令

YUM Commands

源配置文件:/etc/yum.repos.d

cd /etc/yum.repos.d
mv CentOS-Base.repo CentOS-Base.repo.bk
wget http://mirrors.163.com/.help/CentOS7-Base-163.repo
yum makecache
  • yum list
  • yum search 'keyword'
  • yum -y(自动回答 yes) install 包名
  • yum -y update 包名
  • yum -y remove 包名
  • yum grouplist
  • yum groupinstall 软件组名
  • yum groupremove 软件组名

Source Code Installation

指定位置:

  • /usr/local/软件名/
  • /usr/local/src/软件名/

(如上述脚本出错,执行 make clean)

make install

e.g apache /var/www/html/index.html /usr/local/apache/htdocs/index.html

Applications Management Commands

  • desktop shortcut: /usr/share/applications
  • startup apps: gnome-session-properties or gnome-tweaks

Default Management Commands

update-alternatives: maintain symbolic links determining default commands.

sudo update-alternatives --get-selections
sudo update-alternatives --install /usr/bin/x-terminal-emulator
\ x-terminal-emulator /opt/Hyper/hyper 50
sudo update-alternatives --config x-terminal-emulator

APT Key Commands

# Add key
sudo apt-add-repository ppa:user/repo
sudo apt update

# Delete key via last 8 bits
sudo apt-key list
sudo apt-key del 73C62A18
sudo apt update

Network Commands

wget

  • 下载全站资料
  • -P 表示下载到哪个目录
  • -r 表示递归下载
  • -np 表示不下载旁站连接.
  • -k 表示将下载的网页里的链接修改为本地链接.
  • -p 获得所有显示网页所需的元素
wget -r -p -np -k -P ~/tmp/ http://java-er.com

Certificate Bot

CertBot for SSL certificates.

GFW

yum install python-setuptools && easy_install pip
pip install shadowsocks
echo "nohup sslocal -c /etc/shadowsocks.json /dev/null 2>&1 &" /etc/rc.local
nohup ssserver -c /etc/shadowsocks.json -d start /dev/null 2>&1 &

NetWork Management Commands

用途net-tool(被淘汰)iproute2
地址和链路配置ifconfigip addr, ip link
路由表routeip route
邻居arpip neigh
VLANvconfigip link
隧道iptunnelip tunnel
组播ipmaddrip maddr
统计netstatss
ip link show
ip address show
ip route show

# add commands to /etc/init.d/local.sh

rm -fr /etc/udev/rules.d/70-persistent-net.rules

# start up network adapter
ip link set eth0 up

# add/delete static ip
ip address add 192.168.1.1/24 dev eth0
ip address del 192.168.1.1/24 dev eth0

# add/delete static route
ip route add 192.168.1.0/24 dev eth0
ip route del 192.168.1.0/24 dev eth0
ip route add default via 192.168.0.196

# watch packets
watch -n 1 "ifconfig eth0"
watch -n 1 "ifconfig eth1"
watch -n 1 "ifconfig eth2"

ufw

ufw status
ufw enable
ufw allow ssh
ufw allow http
ufw allow https

arp

arp -a显示地址解析协议 (IP 地址—网卡地址):

  • 网际互联层:IP 协议(网际)、IGMP 协议(互联网组管理)、ICMP 协议(互联网控制报文)
  • 传输层:TCP 协议(传输控制)、UDP 协议(用户数据报)

netstat

netstat -an查看本机启用的端口:

  • (-a 查看所有连接和监听端口 -n 显示 IP 地址和端口号)
  • -t tcp 协议端口
  • -u udp 协议端口
  • -l 监听状态服务

nslookup

nslookup domain_name查看 DNS 解析器:

/etc/network/interfaces

主机名:

  • /etc/hostname
  • /etc/sysconfig/network
  • /etc/resolv.conf

ping

ping -c ip/domain探测网络状况

telnet

telnet [ip/domain] [端口]远程管理与端口探测命令

Trace Route

  • traceroute [-n IP] domain路由跟踪命令
  • traceroute -n -I -T -p路由扫描

Net Filter Framework

nftables 命令行工具:nft

fping

fping -a -u -g -f [target]批量扫描主机地址

hping

hping -p -S -a可伪造 IP 地址

mtr

路由扫描

nmap

批量主机服务扫描:

  • -P ICMP
  • -sS TCP SYN
  • -sT TCP connect()
  • -sU UDP

ncat

批量主机服务扫描:

  • -w 设置超时时间
  • -v 显示命令执行过程
  • -z 一个输入输出模式
  • -u UDP 协议

Shell Execution Commands

exec 1>>output.log exec 2>>error.log

Systemctl

systemctl enable local

in /etc/init.d/local

#!/bin/bash
### BEGIN INIT INFO
# Provides: local
# Required-Start: $all
# Required-Stop:
# Default-Start: 3 4 5
# Default-Stop:
# Short-Description: Personal start script

sslocal -c shadowsocks.json -d start

内存控制

sysctl vm [-options] CONFIG
swapoff

Crontab Commands

crontab -l(list)
crontab -e(establish)
  • m,n: 分隔多个时间.
  • m-n: 表示时间范围.
  • /n: 表示每隔 n 时间.
  • 天数星期之间为逻辑或关系.
  • /var/spool/cron/user_name/.
  • /var/log/con.
  • /etc/cron.*ly: 时间表.
  • /etc/anacrontab: 异步时间表.

Background Job Commands

  • jobs —— 所有作业

  • atq —— 延时作业队列

  • at -M(不使用邮件发送运行结果) -f filename deltaTime

  • atrm 作业号/名

  • bg/fg 作业号/名

  • nohup 脚本 & —— 脱离控制台并后台运行脚本

19 ~ -20 (-20 优先级最高)

  • nice -n number 作业号/名
  • renice number -p PID

Startup Job Commands

  • /etc/rc.local —— 系统开机任务
  • /etc/profile/ /etc/bash.bashrc —— bash 启动任务/远程登陆任务
  • /etc/bash.bashrc —— SSH 连接任务

Parallel Execution

命令间插入符

  • command1;command2 顺序执行,相当于 C 语言中语句结束符
  • command1&&command2 命令同时执行(当 1 正确时)或同时不执行(当 1 出错时)
  • command1 || command2 只执行一个命令(正确命令)
  • command1 | command2 前一正确命令的输出结果作为后一命令的输入结果

e.g ls && echo yes >> .log || echo no >> .log

C++ Binary Commands

ldd

ldd ./lib.sio

nm

nm -Ca ./lib.so

Plot Commands

chart.gp

#!/usr/bin/env gnuplot

set term wxt enhanced
set xtics
set view
set multiplot
set size
set origin
fit

plot 'data.dat' using 1:2, 'data.dat' using 1:3
#!/usr/bin/gnuplot -c

set terminal png enhanced
set output ARG1.".png"
set style data linespoints
show timestamp
set title ARG1
set xlabel "time (seconds)"
set ylabel "Segments (cwnd, ssthresh)"
plot ARG1 using 1:7 title "snd_cwnd", \
ARG1 using 1:($8>=2147483647 ? 0 : $8) title "snd_ssthresh"

Shell Scripts

Shell Warnings

  • = 左右无空格.
  • () [] 内部最好有空格.
  • 数值运算用 (())$(()).

文件重定向

  • > 文件设备名: 覆盖标准输出重定向.
  • >> 文件设备名: 追加标准输出重定向.
  • 2>文件设备名: 覆盖错误输出重定向.
  • 2>>文件设备名: 追加错误输出重定向.
  • >/>> 文件 2>&1 &>/&>>文件: 覆盖/追加正确输出与错误输出同时重定向.
  • < 文件设备名/<< 文件设备名: 覆盖/追加标准输入重定向.

Here Document

command << END
...
END

command << EOF
...
EOF
#!/bin/bash
gnuplot -persist <<EOF
set data style linespoints
show timestamp
set title "$1"
set xlabel "time (seconds)"
set ylabel "Segments (cwnd, ssthresh)"
plot "$1" using 1:7 title "snd_cwnd", \\
"$1" using 1:($8>=2147483647 ? 0 : $8) title "snd_ssthresh"
EOF

变量

基本变量

  • = : 左右两端不可有空格.
  • ' ': 完全标准字符串.
  • " ": 格式化字符串.
  • 调用变量值:$变量名.
  • set/unset: 设置/取消变量.

built-in 变量

  • $*/$@: argv[1], ..., argv[n]
  • $0/$1/../$n: argv[0], ..., argv[n]
  • $#: argc
  • $?: exit code of last command
if [ "$?" -ne "0" ];then
echo "sorry, command execution failed!"
fi

每次 shift 命令执行的时候, 变量 $2 的值会移动到变量 $1 中, 变量 $3 的值会移动到变量 $2 中. 变量 $# 的值也会相应的减 1.

#!/bin/bash
# posit-param2: script to display all arguments
count=1
while [[ $# -gt 0 ]]; do
echo "Argument $count = $1"
count=$((count + 1))
shift
done
usage () {
echo "$PROGNAME: usage: $PROGNAME [-f file | -i]"
return
}
# process command line options
interactive=
filename=
while [[ -n $1 ]]; do
case $1 in
-f | --file) shift
filename=$1
;;
-i | --interactive) interactive=1
;;
-h | --help) usage
exit
;;
*) usage >&2
exit 1
;;
esac
shift
done

环境变量

  • /etc/profile.d/*.sh.
  • ~/.bash_profile.
  • ~/.bashrc.
  • /etc/profile.
  • /etc/bash.bashrc.
  • /etc/issue: shell 登录信息.
  • PS1 环境变量: shell 头行打印信息.
  • PATH 环境变量.
Environment Command
  • env: 查看环境变量.
  • export 变量名=变量值: 设置环境变量.
  • printenv.

数值运算

declare 命令

Bash Expansions

  • $(()) or $[]: arithmetic expansion

一般地, 将数值运算用 (()) [[]]$(()) 括起, 可以确保变量不会被识别为 string

read x
read y

echo $((x + y))
echo $((a < b ? a : b))

if ((a > b))
then
echo "a > b"
fi

if [[ a -gt b ]]
then
echo "a > b"
fi

if [ "$a" -gt "$b" ]
then
echo "a > b"
fi
  • [[ xxx ]]: condition
  • (( xxx )): arithmetic condition
operatorfunction
! EXPRESSIONThe EXPRESSION is false
-n STRINGThe length of STRING is greater than zero
-z STRINGThe length of STRING is zero (ie it is empty)
STRING1 == STRING2STRING1 is equal to STRING2
STRING1 != STRING2STRING1 is not equal to STRING2
STRING1 > STRING2STRING1 sorts after STRING2
STRING1 < STRING2STRING1 sorts before STRING2
INTEGER1 -eq INTEGER2INTEGER1 is numerically equal to INTEGER2
INTEGER1 -gt INTEGER2INTEGER1 is numerically greater than INTEGER2
INTEGER1 -lt INTEGER2INTEGER1 is numerically less than INTEGER2
-d FILEFILE exists and is a directory
-e FILEFILE exists
-r FILEFILE exists and the read permission is granted
-s FILEFILE exists and it's size is greater than zero
-w FILEFILE exists and the write permission is granted
-x FILEFILE exists and the execute permission is granted
AND -a &&
OR -o ||
NOT ! !
  • : group regexp
echo a{A{1,2},B{3,4}}b
aA1b aA2b aB3b aB4b
  • ${}: string expansion
    • ${parameter:-word}: 若 parameter 没有设置(例如,不存在)或者为空,展开结果是 word 的值。 若 parameter 不为空,则展开结果是 parameter 的值
    • ${parameter:+word}: 若 parameter 没有设置或为空,展开结果为空。 若 parameter 不为空, 展开结果是 word 的值会替换掉 parameter 的值
    • ${parameter:=word}: 若 parameter 没有设置或为空,展开结果是 word 的值。 另外,word 的值会赋值给 parameter。 若 parameter 不为空,展开结果是 parameter 的值
    • ${parameter:?word}: 若 parameter 没有设置或为空,这种展开导致脚本带有错误退出, 并且 word 的内容会发送到标准错误。 若 parameter 不为空, 展开结果是 parameter 的值
    • ${!prefix*} ${!prefix@}: 这种展开会返回以 prefix 开头的已有变量名
    • ${#parameter}: 展开成由 parameter 所包含的字符串的长度
    • ${parameter:offset} ${parameter:offset:length}: 提取一部分字符
    • ${parameter,,} 把 parameter 的值全部展开成小写字母
    • ${parameter,} 仅仅把 parameter 的第一个字符展开成小写字母
    • ${parameter^^} 把 parameter 的值全部转换成大写字母
    • ${parameter^} 仅仅把 parameter 的第一个字符转换成大写字母
    • ${parameter#pattern} ${parameter##pattern}, ${parameter%pattern} ${parameter%%pattern}: 从 parameter 所包含的字符串中清除开头/末尾一部分文本
    • ${parameter/pattern/string}, ${parameter//pattern/string}, ${parameter/#pattern/string}, ${parameter/%pattern/string}: replace
foo=file.txt.zip
echo ${foo#*.}
txt.zip
echo ${foo##*.}
zip

foo=file.txt.zip
echo ${foo%.*}
file.txt
echo ${foo%%.*}
file
foo=JPG.JPG
echo ${foo/JPG/jpg}
jpg.JPG
echo ${foo//JPG/jpg}
jpg.jpg
echo ${foo/#JPG/jpg}
jpg.JPG
echo ${foo/%JPG/jpg}
JPG.jpg
  • $(): command result.
  • "": allow expansions string.
  • '': disallow expansions string.

流程控制语句

if 语句

if [[ 条件判断式 ]] ; then
程序
fi
if [[ 条件判断式 ]]
then
程序
else
程序
fi

if [[ 条件判断式1 ]]
then
程序1
elif [[ 条件判断式2 ]]
then
程序2
else
程序n
fi
#!/usr/bin/bash

i=1;
for flag in "$@"
do
if [[ $flag == "-o" ]]
then
open=1;
fi
done

exclude="--exclude-dir=node_modules --exclude-dir=build --exclude-dir=.yarn --exclude-dir=.cache --exclude-dir=.next --exclude-dir=coverage --exclude-dir=public --exclude-dir=.git --exclude-dir=dist --exclude=package-lock.json --exclude=yarn.lock --exclude=CHANGELOG.md"

if [[ -n $open ]]
then
grep -r $1 $exclude | awk -F : '{print $1}' | xargs code;
else
grep -r $1 $exclude;
fi

case 语句

case $变量名 in
“值1”)
程序
;;
“值2”)
程序
;;
*)
程序
;;
esac
case patternfunction
a)word equals "a"
[[:alpha:]])word is a single alphabetic character
???)word is exactly three characters long
*.txt)word ends with the characters “.txt”
*)any value of word
#!/bin/bash
# case-menu: a menu driven system information program
clear
echo "
Please Select:
1. Display System Information
2. Display Disk Space
3. Display Home Space Utilization
0. Quit
"
read -p "Enter selection [0-3] > "
case $REPLY in
0) echo "Program terminated."
exit
;;
1) echo "Hostname: $HOSTNAME"
uptime
;;
2) df -h
;;
3) if [[ $(id -u) -eq 0 ]]; then
echo "Home Space Utilization (All Users)"
du -sh /home/*
else
echo "Home Space Utilization ($USER)"
du -sh $HOME
fi
;;
*) echo "Invalid entry" >&2
exit 1
;;
esac

or case pattern

#!/bin/bash
# case-menu: a menu driven system information program
clear
echo "
Please Select:
A. Display System Information
B. Display Disk Space
C. Display Home Space Utilization
Q. Quit
"
read -p "Enter selection [A, B, C or Q] > "
case $REPLY in
q|Q) echo "Program terminated."
exit
;;
a|A) echo "Hostname: $HOSTNAME"
uptime
;;
b|B) df -h
;;
c|C) if [[ $(id -u) -eq 0 ]]; then
echo "Home Space Utilization (All Users)"
du -sh /home/*
else
echo "Home Space Utilization ($USER)"
du -sh $HOME
fi
;;
*) echo "Invalid entry" >&2
exit 1
;;
esac

fall through case pattern (;;&)

#!/bin/bash
# case4-2: test a character
read -n 1 -p "Type a character > "
echo
case $REPLY in
[[:upper:]]) echo "'$REPLY' is upper case." ;;&
[[:lower:]]) echo "'$REPLY' is lower case." ;;&
[[:alpha:]]) echo "'$REPLY' is alphabetic." ;;&
[[:digit:]]) echo "'$REPLY' is a digit." ;;&
[[:graph:]]) echo "'$REPLY' is a visible character." ;;&
[[:punct:]]) echo "'$REPLY' is a punctuation symbol." ;;&
[[:space:]]) echo "'$REPLY' is a whitespace character." ;;&
[[:xdigit:]]) echo "'$REPLY' is a hexadecimal digit." ;;&
esac

for 语句

for 变量 in 值1 值2 值3 …… 值n
do
程序
done

$(seq 1 50) # 1 2 ... 50
{1..50} # 1 2 ... 50
{0..10..2} # 0 2 4 6 8 10

for (( 初始值;循环控制条件;变量变化 )); do
程序
done

while 语句与 until 语句

while [[ 条件判断式 ]]
do
程序
done

until [[ 条件判断式 ]]
do
程序
done
(( expression1 ))
while (( expression2 )); do
commands
(( expression3 ))
done
#!/bin/bash
# while-menu: a menu driven system information program
DELAY=3 # Number of seconds to display results
while [[ $REPLY != 0 ]]; do
clear
cat <<- _EOF_
Please Select:
1. Display System Information
2. Display Disk Space
3. Display Home Space Utilization
0. Quit
_EOF_
read -p "Enter selection [0-3] > "
if [[ $REPLY =~ ^[0-3]$ ]]; then
if [[ $REPLY == 1 ]]; then
echo "Hostname: $HOSTNAME"
uptime
sleep $DELAY
fi
if [[ $REPLY == 2 ]]; then
df -h
sleep $DELAY
fi
if [[ $REPLY == 3 ]]; then
if [[ $(id -u) -eq 0 ]]; then
echo "Home Space Utilization (All Users)"
du -sh /home/*
else
echo "Home Space Utilization ($USER)"
du -sh $HOME
fi
sleep $DELAY
fi
else
echo "Invalid entry."
sleep $DELAY
fi
done
echo "Program terminated."
#!/bin/bash
# while-read: read lines from a file
while read dist version release; do
printf "Dist: %s\tVersion: %s\tReleased: %s\n" \
$dist \
$version \
$release
done < dist.txt

do while statement

while : ; do
actions
[[ current_time <= $cutoff ]] || break
done

Bash Array

Bash Function

  • 函数局部变量 local 变量名.
  • 函数参数 : $/+/#/?/@/n.
  • 引用函数库文件: source sh 文件名/. sh 文件名, 可修改 ~/.bashrc 文件.

Bash IO

#!/bin/bash
# read-validate: validate input
invalid_input () {
echo "Invalid input '$REPLY'" >&2
exit 1
}
read -p "Enter a single item > "
# input is empty (invalid)
[[ -z $REPLY ]] && invalid_input
# input is multiple items (invalid)
(( $(echo $REPLY | wc -w) > 1 )) && invalid_input
# is input a valid filename?
if [[ $REPLY =~ ^[-[:alnum:]\._]+$ ]]; then
echo "'$REPLY' is a valid filename."
if [[ -e $REPLY ]]; then
echo "And file '$REPLY' exists."
else
echo "However, file '$REPLY' does not exist."
fi
# is input a floating point number?
if [[ $REPLY =~ ^-?[[:digit:]]*\.[[:digit:]]+$ ]]; then
echo "'$REPLY' is a floating point number."
else
echo "'$REPLY' is not a floating point number."
fi
# is input an integer?
if [[ $REPLY =~ ^-?[[:digit:]]+$ ]]; then
echo "'$REPLY' is an integer."
else
echo "'$REPLY' is not an integer."
fi
else
echo "The string '$REPLY' is not a valid filename."
fi
#!/bin/bash
# read-menu: a menu driven system information program
clear
echo "
Please Select:

1. Display System Information
2. Display Disk Space
3. Display Home Space Utilization
0. Quit
"
read -p "Enter selection [0-3] > "

if [[ $REPLY =~ ^[0-3]$ ]]; then
if [[ $REPLY == 0 ]]; then
echo "Program terminated."
exit
fi
if [[ $REPLY == 1 ]]; then
echo "Hostname: $HOSTNAME"
uptime
exit
fi
if [[ $REPLY == 2 ]]; then
df -h
exit
fi
if [[ $REPLY == 3 ]]; then
if [[ $(id -u) -eq 0 ]]; then
echo "Home Space Utilization (All Users)"
du -sh /home/*
else
echo "Home Space Utilization ($USER)"
du -sh $HOME
fi
exit
fi
else
echo "Invalid entry." >&2
exit 1
fi
# interactive mode
if [[ -n $interactive ]]; then
while true; do
read -p "Enter name of output file: " filename
if [[ -e $filename ]]; then
read -p "'$filename' exists. Overwrite? [y/n/q] > "
case $REPLY in
Y|y) break
;;
Q|q) echo "Program terminated."
exit
;;
*) continue
;;
esac
elif [[ -z $filename ]]; then
continue
else
break
fi
done
fi

信号

  • man 7 signal: 传递信号给进程.
  • CTRL + C: SIGINT.
  • CTRL + Z: SIGSTP.
  • kill/killall: SIGINT.
  • trap SIG*/trap EXIT: 捕捉信号(后 + 忽略信号/默认处理信号/自定义处理信号).
  • trap – SIG*/trap - EXIT: 移除信号.

Bash Debugging

-x option:

#!/bin/bash -x
# trouble: script to demonstrate common errors
number=1
if [ $number = 1 ]; then
echo "Number is equal to 1."
else
echo "Number is not equal to 1."
fi
#!/bin/bash
# trouble: script to demonstrate common errors
number=1
echo "number=$number" # DEBUG
set -x # Turn on tracing
if [ $number = 1 ]; then
echo "Number is equal to 1."
else
echo "Number is not equal to 1."
fi
set +x # Turn off tracing

Shell Script Best Practices

  • Google Shell Style Guide
  • 指定默认解释器cat /etc/shells
  • 设置bash strict mode
  • 条件判断使用[[ ]]
  • 使用变量时用双引号把变量包起来 cp -r "$src_dir" "$dest_dir"
  • 使用$()获取表达式的值
  • 使用${arr[@]}进行列表循环
#!/usr/bin/env bash

# 设置命令回显
set -x

# 遇到未声明的变量则报错停止
set -u
# 遇到执行错误则停止
set -e
# 管道命令其中一步失败则中止
set -o pipefail

Interactive Shell Script Tips

Check Root Validation

if (( $EUID != 0 )); then
echo "Please run as root!"
exit
fi
# run as root directly
sudo chown root <filename>
sudo chmod +s <filename>

Bash help option

#!/bin/sh
if [[ ${#@} -ne 0 ]] && [[ "${@#"--help"}" = "" ]]; then
printf -- '...help...\n';
exit 0;
fi;

Bash Silent Option

#!/bin/sh
if [[ ${#@} -ne 0 ]] && [[ "${@#"--silent"}" = "" ]]; then
stty -echo;
fi;
# ...
# before point of intended output:
stty +echo && printf -- 'intended output\n';
# silence it again till end of script
stty -echo;
# ...
stty +echo;
exit 0;

Check Command Validation

#!/bin/sh
_=$(command -v docker);
if [[ "$?" != "0" ]]; then
printf -- 'You don\'t seem to have Docker installed.\n';
printf -- 'Get it: https://www.docker.com/community-edition\n';
printf -- 'Exiting with code 127...\n';
exit 127;
fi;
Get Absolute Path
#!/bin/sh
CUR_DIR="$(dirname $0);"
printf -- 'moving application to /opt/app.jar';
mv "${CUR_DIR}/application.jar" /opt/app.jar;

Bash error handle

#!/bin/sh
error_handle() {
stty echo;
}

if [[ ${#@} -ne 0 ]] && [[ "${@#"--silent"}" = "" ]]; then
stty -echo;
trap error_handle INT;
trap error_handle TERM;
trap error_handle KILL;
trap error_handle EXIT;
fi;
# ...

Bash loading progress

#!/bin/sh
printf -- 'Performing asynchronous action..';
./trigger-action;
DONE=0;
while [ $DONE -eq 0 ]; do
./async-checker;
if [ "$?" = "0" ]; then DONE=1; fi;
printf -- '.';
sleep 1;
done;
printf -- ' DONE!\n';

Zsh

# Install zsh and powerline
sudo apt install zsh powerline powerline-status

# Install oh-my-zsh
sh -c "$(wget -O- https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

# Install zsh themes
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k
git clone --depth=1 https://github.com/sabertazimi/dragon-zsh-theme.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/dragon

# Install zsh plugins
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting
git clone https://github.com/lukechilds/zsh-nvm ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-nvm

plugins=(
command-not-found fzf git git-prompt github
history lighthouse man node npm nvm pm2 vi-mode yarn
)

Terminal

Terminal Basis

  • 电传打字机 (TeleTypeWriter, TTY) 是物理设备, 最初是为电报设计, 后来被连接到计算机上, 发送输入和获取输出.
  • 电传打字机 (TTY) 现在被运行在内核中的模块所模拟, 被称为终端模拟器 (Terminal Emulator).
  • 伪终端 (Pseudo Terminal, PTY) 是运行在用户区的终端模拟程序.
  • Shell 由 Terminal fork 出来, 是 Terminal 的子进程. Terminal 处理键盘事件, 负责字符的显示. Shell 负责解释执行用户输入的字符, 返回操作系统底层响应.
  • 可以使用 stty 命令对 TTY 设备进行配置.
  • 远程终端 ssh 也是一种伪终端 PTY:
    • Local: PTY Master is Terminal, PTY Slave is bash and ssh client.
    • Remote: PTY Master is ssh server, PTY Slave is bash.

Default Terminal

update-alternatives: maintain symbolic links determining default commands.

sudo update-alternatives --get-selections
sudo update-alternatives --install /usr/bin/x-terminal-emulator
\ x-terminal-emulator /opt/Hyper/hyper 50
sudo update-alternatives --config x-terminal-emulator

Tmux

Basic Tmux Commands

tmux ls
tmux new -s sessionID
tmux a -t sessionID # attach
tmux show -g >> current.tmux.conf # export configuration

Basic Hotkeys

?        # 快捷键帮助列表
Session management
:new<CR> # 创建新的 Session,其中 : 是进入 Tmux 命令行的快捷键
s list sessions
$ rename the current session
d detach from the current session
Tmux Windows Hotkeys
c create a new window
, rename the current window
w list windows
% split horizontally
" split vertically
n change to the next window
p change to the previous window
0 to 9 select windows 0 through 9
Tmux Panes Hotkeys
% create a horizontal pane
" create a vertical pane
<space> # 切换 Pane 布局
h move to the left pane. *
j move to the pane below *
l move to the right pane *
k move to the pane above *
q show pane numbers
o toggle between panes
} swap with next pane
{ swap with previous pane
! break the pane out of the window
x kill the current pane
t # 显示一个时钟
Tmux Scroll
  • C-a + [ to into scroll mode, q to quit scroll mode
  • copy mode can scroll too
  • set -g mouse on for enabling mouse scrolling

Tmux Configuration

# C-b is not acceptable -- Vim uses it
set-option -g prefix C-a
bind-key C-a last-window

# Start numbering at 1
set -g base-index 1

# Allows for faster key repetition
set -s escape-time 0

# Set status bar
set -g status-bg black
set -g status-fg white
set -g status-left ""
set -g status-right "#[fg=green]#H"

# Enable scroll mouse
set -g mouse on

# Rather than constraining window size to the maximum size of any client
# connected to the *session*, constrain window size to the maximum size of any
# client connected to *that window*. Much more reasonable.
setw -g aggressive-resize on

# Allows us to use C-a a <command> to send commands to a TMUX session inside
# another TMUX session
bind-key a send-prefix

# Reload configuration
bind r source-file ~/.tmux.conf \; display-message "Config reloaded"

# Escape to enter copy mode, v to selection, y to yank, p to paste
bind Escape copy-mode
bind-key -T copy-mode-vi 'v' send -X begin-selection
bind-key -T copy-mode-vi 'y' send -X copy-selection-and-cancel
# bind-key -t vi-copy v begin-selection
# bind-key -t vi-copy y copy-pipe "reattach-to-user-namespace pbcopy"
unbind p
bind p pasteb

setw -g mode-keys vi # Vi

# Highlight active window
set-window-option -g window-status-current-bg red

Perf Tools

Top Command

top

dmesg

dmesg | tail

iostat

iostat -xz 1

free

free -m

sar

`sar -n DEV 1`
`sar -n TCP,ETCP 1`

perf

Perf Examples

perf list # events
perf stat <command>
perf stat -e <events> <command>
perf record -e <events> -a <command>
perf report

Linux Tools

FFmpeg

Media conversion:

# https://www.yanxurui.cc/posts/tool/2017-10-07-use-ffmpeg-to-edit-video
ffmpeg -global_options -input_1_options -i input_1 -input_2_options -i input_2 \
-output_1_options output_1 ...

FFmpeg Probe

ffprobe input.mp4
ffmpeg -hide_banner -i input.mkv

FFmpeg Transform

  • MP4: H264Video + ACCAudio
  • WebM: VP8Video + VorbisAudio
  • OGG: TheoraVideo + VorbisAudio
# code decoder information
ffmpeg -codecs
# mkv to mp4
ffmpeg -i input.mkv -codec copy output.mp4
# compress
ffmpeg -i input.mkv -c copy -c:v libx264 -vf scale=-2:720 output.mkv
# make mkv with video and subtitle
ffmpeg -i input.avi -i input.srt \
-map 0:0 -map 0:1 -map 1:0 -c:v libx264 -c:a aac -c:s srt output.mkv
# flac to mp3
ffmpeg -i "Michael Jackson - Billie Jean.flac" \
-ab 320k "Michael Jackson - Billie Jean.mp3"
ffmpeg -i music_flac.flac \
-acodec libmp3lame \
-ar 44100 \
-ab 320k \
-ac 2 music_flac_mp3.mp3
# - acodec: Audio Coder Decoder 音频编码解码器
# - libmp3lame: MP3 解码器
# - ar: audio rate 音频采样率, 默认用原音频的采样率
# - ab: audio bit rate 音频比特率, 默认 128K
# - ac: audio channels 音频声道, 默认采用源音频的声道数
# mp4 to avi
ffmpeg -i video.mp4 \
-s 1920x1080 \
-pix_fmt yuv420p \
-vcodec libx264 \
-preset medium \
-profile:v high \
-level:v 4.1 \
-crf 23 \
-r 30 \
-acodec aac \
-ar 44100 \
-ac 2 \
-b:a 128k video_avi.avi
# - s: 缩放视频新尺寸 (size)
# - pix_fmt:pixel format, 设置视频颜色空间
# - vcodec: Video Coder Decoder, 视频编码解码器
# - preset: 编码器预设
# - profile:v: 编码器配置, 与压缩比有关. 实时通讯-baseline, 流媒体-main, 超清视频-high
# - level:v: 对编码器设置的具体规范和限制, 权衡压缩比和画质
# - crf: 设置码率控制模式, constant rate factor恒定速率因子模式, 范围 0~51, 数值越小, 画质越高
# - r:设置视频帧率
# - b:a: 音频比特率, 大多数网站限制音频比特率 128k, 129k
# Scale pictures
ffmpeg -i input.jpg -vf scale=320:240 output_320x240.png

FFmpeg Cutting

# audio only
ffmpeg -i cut.mp4 -vn output.mp3
ffmpeg -i video.mp4 -vn -acodec copy video_noVideo.m4a

# video only
ffmpeg -i video.mp4 -vcodec copy -an video_silent.mp4
# from to cutting
ffmpeg -i music.mp3 -ss 00:00:30 -to 00:02:00 -acodec copy music_cutout.mp3
ffmpeg -i in.mp4 -ss 00:01:00 -to 00:01:10 -c copy out.mp4
ffmpeg -ss 00:01:00 -i in.mp4 -to 00:01:10 -c copy -copyts out.mp4

# 30s duration cutting
ffmpeg -ss 00:02:00.0 -i input.mkv -t 30 -c copy output.mkv
ffmpeg -i input.mkv -ss 00:02:00.0 -t 30 -c copy output.mkv
ffmpeg -ss 00:01:30.0 -i input.mkv -ss 00:00:30.0 -t 30 output.mkv

FFmpeg Mixing

# replace audio
ffmpeg -i input.mkv -i input.mp3 -map 0:v -map 1:a -c copy -shortest output.mp4

# merge audio and video
ffmpeg -i video_noVideo.m4a -i video_silent.mp4 -c copy video_merge.mp4

ffmpeg -i "concat:01.mp4|02.mp4|03.mp4" -c copy out.mp4

ffmpeg -i input.mkv -i output.aac \
-filter_complex "[0:a][1:a]amerge=inputs=2[a]" -map 0:v -map "[a]" \
-c:v copy -c:a aac -ac 2 -shortest output.mp4
# Merge pictures
ffmpeg -i 1.png -i 2.png -filter_complex "vstack" output.png

FFmpeg Screenshot

# -vf -> -filter:v
ffmpeg -ss 00:30:14.435 -i input.mkv -vframes 1 out.png
ffmpeg -i input.mkv -vf fps=1/60 -strftime 1 out_%Y%m%d%H%M%S.jpg

FFmpeg Gif

ffmpeg -i video.mp4 -ss 7.5 -to 8.5 -s 640x320 -r 15 video_gif.gif

palette="/tmp/palette.png"
filters="fps=10,scale=-1:144:flags=lanczos"
ffmpeg -ss 30 -t 5 -i input.mp4 -vf "$filters,palettegen" -y $palette
ffmpeg -ss 30 -t 5 -i input.mp4 -i $palette \
-filter_complex "$filters [x]; [x][1:v] paletteuse" -y output.gif

FFmpeg Subtitle

ffmpeg -i input.mkv -vf subtitles=input.srt output.mp4
ffmpeg -i input.mkv -vf ass=input.ass output.mp4

FFmpeg Watermark

ffmpeg -i input.mkv -i input.png \
-filter_complex "overlay=W-w-5:5" -c copy -c:v libx264 output.mkv

FFmpeg Desktop Recording

# windows
ffmpeg -f gdigrab -i desktop rec.mp4

# linux
sudo ffmpeg -f fbdev -framerate 10 -i /dev/fb0 rec.mp4

FFmpeg Live Streaming

ffmpeg -re i rec.mp4 按照网站要求编码 -f flv "你的 RTMP 地址/你的直播码"

Nginx

  • /etc/nginx/sites-available: sites config
nginx -t # check config syntax

Nginx Basic Configuration

泛域名路径分离: xxx.test.dev -> /usr/local/html/xxx

server {
listen 80;
server_name ~^([\w-]+)\.test\.dev$;
root /usr/local/html/$1;
}
server {
# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
root /var/www/html/;

# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;

server_name example.tld www.example.tld;

# Cache static assets
location ~* \.(?:jpg|jpeg|gif|png|ico|svg)$ {
expires 7d;
add_header Cache-Control "public";
}

location ^~ /assets/ {
gzip_static on;
expires 12h;
add_header Cache-Control "public";
}

# Cache css and js bundle
location ~* \.(?:css|js)$ {
add_header Cache-Control "no-cache, public, must-revalidate, proxy-revalidate";
}

location / {
include /etc/nginx/mime.types;
try_files $uri $uri/ /index.html;
# try_files $uri $uri/ =404;

# proxy_http_version 1.1;
# proxy_cache_bypass $http_upgrade;
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection 'upgrade';
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto $scheme;
# proxy_pass http://localhost:3000;
}
}

Namespaces and Cgroup

Namespaces

# PID Namespace
unshare --fork --pid --mount-proc /bin/bash
ps -aux

# Mount Namespace
unshare --fork --mount /bin/bash
mkdir /tmp/mnt
mount -t tmpfs -o size=1m tmpfs /tmp/mnt
df -h |grep mnt

# User Namespace
PS1='\u@container#' unshare --user -r /bin/bash

# UTS Namespace (isolated hostname)
unshare --fork --uts /bin/bash
hostname -b container

# IPC Namespace
unshare --fork --ipc /bin/bash
ipcmk -Q
ipcs -q

# Net Namespace
unshare --fork --net /bin/bash
ip addr
netstat -ntlp

Cgroup

Cgroup (Linux Control Group): limit process group resources usage, including CPU, Memory, Disk I/O, Network Bandwidth etc.

  • Resource usage limit.
  • Priority.
  • Resource record.
  • Process Control.

List cgroup

mount -t cgroup
ls -l /sys/fs/cgroup/

Create cgroup

mkdir /sys/fs/cgroup/cpu/loop
ls -l /sys/fs/cgroup/cpu/loop
cat /sys/fs/cgroup/cpu/loop/cpu.cfs_period_us # 100000us
cat /sys/fs/cgroup/cpu/loop/cpu.cfs_quota_us # -1 (no limit)

Resource control via cgroup

# limit cpu usage to 50%
echo 50000 >/sys/fs/cgroup/cpu/loop/cpu.cfs_quota_us

# add pid to `loop` cgroup
echo 21497 >/sys/fs/cgroup/cpu/loop/tasks