【Linux】基础 Linux 命令

Tip: 查看命令手册

$ man <command>

$ man man

 The sections of the manual are:
	   1. General Commands Manual
	   2. System Calls Manual
	   3. Library Functions Manual
	   4. Kernel Interfaces Manual
	   5. File Formats Manual
	   6. Games Manual
	   7. Miscellaneous Information Manual
	   8. System Manager's Manual
	   9. Kernel Developer's Manual

学习命令时我们常去查找手册,但手册内容太过详实,我们难以在其中找到最常用的标记和语法。 TLDR 提供了一些案例,可以帮助我们快速找到正确的选项。下面对常用的 Linux 命令进行汇总。

文件操作

创建目录/复制文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# 创建多层次、多维度的目录树
mkdir -p Project/{a,b,c,d}/src
mkdir sa{1..50}
mkdir test{01..10}
mkdir {a-z}12345 

# copy
cp a target_dir

cp a b c target_dir  # 复制多个文件
cp -r data/ new_dir  # 文件夹
 
# 复制一个文件夹下的多个文件
# cp file_a/a file_a/b file_a/c target_dir
cp ./{a,b,c} target_dir

# 复制名称相似的多个文件
cp a_[1-4] target_dir    # a_1,a_2,a_3,a_4 -> target_dir
cp a_[1,2,4] target_dir  # a_1,a_2,a_4     -> target_dir

rename 修改文件名

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# a_01、a_02 -> b_01, b_02
rename a b *
# Perl语言版本格式:rename 's/原字符串/新字符串/' 文件名
rename 's/a/b/' *

# 修改文件的后缀 //把.html 后缀的改成 .php后缀
rename "s//.html//.php/" *    
 
# 批量添加文件后缀 //把所有的文件名都以txt结尾
rename "s/$//.txt/" *    
 
# 批量删除文件名 //把所有以.txt结尾的文件名的.txt删掉
rename "s//.txt//" *
# pate_99.tml.tml -> pate_99.tml
rename -n 's/.tml//' *  # -n 显示修改效果

查找文件位置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
find . -name '.gitignore'
sudo find /usr/local/bin -type l -ilname "/opt/node/*" -print -delete
# 递归的查找文件夹中最近使用的文件
# xargs: execute a command using STDIN as arguments
find . -type f -mmin -60 -print0 | xargs -0 ls -lt | head -1

# 查找所有名称为src的文件夹
find . -name src -type d
# 查找所有文件夹路径中包含test的python文件
find . -path '*/test/*.py' -type f
# 查找前一天修改的所有文件
find . -mtime -1
# 查找所有大小在500k至10M的tar.gz文件
find . -size +500k -size -10M -name '*.tar.gz'

# 删除全部扩展名为.tmp 的文件
find . -name '*.tmp' -exec rm {} \;

工具

压缩 解压

1
2
3
tar xvfz uimaj-2.6.0-bin.tar.gz
zip -r tqa_data.zip data/
unzip -d /tqa_data tqa_data.zip

下载

1
2
# 后台下载 + 断点续传(记得关代理-大流量-速度慢)
wget -b -c http://place.your.url/here

文件传输

  • ssh + tee
1
cat localfile | ssh remote_server tee serverfile
  • scp

scp (secure copy) 的底层是 SSH 协议,默认端口22,相当于 ssh + cp,即先使用 ssh 命令登录远程主机,然后再执行拷贝操作。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 本地文件复制到远程
scp SourceFile user@host:directory/TargetFile

# 将本机的 documents 目录拷贝到远程主机,会在远程主机创建 documents 目录
$ scp -r documents username@server_ip:/path_to_remote_directory

---
# 远程文件复制到本地
scp user@host:directory/SourceFile TargetFile

# 两个远程系统之间的复制
scp user@host1:directory/SourceFile user@host2:directory/SourceFile

两个服务器之间 scp,可能会因目标机器的文件夹权限不够导致无法传输,这是可以修改文件夹权限,或先复制到目标机器 /tmp 目录作为中转。

rsync 对 scp 进行了改进,两者语法相似,rsync可以检测本地和远端的文件以防止重复拷贝,可以提供一些诸如符号连接、权限管理等精心打磨的功能,甚至还可以基于 --partial 标记实现断点续传。

1
rsync -aAXv /path/to/sitename/public/ user@remote:/var/www/mysite --delete
  • sz rz
  • ftp

资源监控

使用 top 命令完成系统资源的通用监控(内存、CPU 占用率等等均统一显示),各指标含义可见文档。htop 是 top 的升级版本。

1
2
3
4
5
top   # 按1: 展开每个 CPU 情况 
      # P:按%CPU使用率排行
      # T:按TIME+排行
      # M:按%MEM排行
htop

查看进程信息

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# ps aux:用户、PID、% CPU 使用率、% 内存使用率、VSZ(虚拟内存大小)、RSS(常驻集大小)、
# TTY(与进程关联的终端)、STAT(进程状态)、START(启动时间)和 COMMAND(启动进程的命令)
ps aux | grep -v grep | grep uname | grep python
ps aux | grep uname | grep -v grep | grep -v vscode | grep python | awk '{print $2}' | xargs -r kill -9

alias pspy="ps aux | grep uname | grep -v grep | grep -v vscode | grep python"
alias killpy='ps aux | grep uname | grep -v grep | grep -v vscode | grep python | awk "{print \$2}" | xargs -r kill -9'

# ps -fe:用户、进程ID(PID)、父进程ID(PPID)、CPU和内存使用情况、启动时间以及命令
ps -fe

查看系统内存使用情况

1
2
3
4
$ free -h
              total        used        free      shared  buff/cache   available
Mem:           15Gi       1.2Gi        11Gi       3.0Mi       2.8Gi        13Gi
Swap:         4.0Gi          0B       4.0Gi

查看系统磁盘使用/负载情况

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 使用的磁盘空间总和 disk usage
du -sh .
# 当前目录文件夹大小
du -h --max-depth=1

# 磁盘剩余空间(以磁盘分区为单位)disk free
df -hl

# 分析磁盘使用情况 NCurses Disk Usage
ncdu /path/to/directory

# 查看磁盘IO负载情况
iostat -d -k 3 5    # -d:显示磁盘的使用情况
					# -k:以KB为单位显示
					# 3:统计时间间隔
					# 5:统计次数

查看文件信息

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# file 查看文件基本信息
$ file ./client
./client: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=94b9574ee39e79a115f61f1f566dcc2ad6845465, for GNU/Linux 3.2.0, not stripped

# lsof 列出被进程打开的文件和网络连接
$ lsof

# 查看依赖的库文件
$ ldd server
        linux-vdso.so.1 (0x00007ffc419f3000)
        libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007f37aa46d000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f37aa44a000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f37aa258000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f37aa49b000)

查看主机内核信息

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
$ cat /proc/version
Linux version 2.6.32-642.el6.x86_64 (mockbuild@worker1.bsys.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-17) (GCC) ) #1 SMP Tue May 10 17:27:01 UTC 2016

$ uname -r
2.6.32-642.el6.x86_64

$ uname -a
# WSL ubuntu
Linux localhost.localdomain 2.6.32-642.el6.x86_64 #1 SMP Tue May 10 17:27:01 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
# ubuntu
Linux aliyun-ecs 5.15.0-71-generic #78-Ubuntu SMP Tue Apr 18 09:00:29 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
# macos
Darwin elf-MacBook-Pro.local 23.1.0 Darwin Kernel Version 23.1.0: Mon Oct  9 21:27:24 PDT 2023; root:xnu-10002.41.9~6/RELEASE_ARM64_T6000 arm64
x86 → 32位
x86_64 = x64 = AMD64

vim 文本编辑

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 配置语法高亮
:syntax on
:syntax off

# 强制保存(w !command)(%: the current buffer's filename)
:w !sudo tee %

:%s/old/new/g # 全部替换(g)
:%!grep -e execve  # 过滤

sudo echo 3 > brightnes # 报错
echo 3 | sudo tee brightness # ok

# copy to system clipboard
# the register named * is the system clipboard
"*y
"*p

# 从 stdout 读取输出作为临时文件
strace -f gcc hello.c |& vim -

终端多路复用

screen\tmux,screen够用但与zsh冲突

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# To list all your sessions
screen -ls
# Kill detached screen session -
screen -S 12562 -X quit

# 创建名为 workname 的离线 session 并执行命令
screen -S workname -dm command
screen -S workname -dm bash -c 'script.sh > log 2>&1'
screen -r workname   # resume 进入名为 workname 的session
# detach current
screen -d
# kill
screen -S workname -X quit

脚本

编写脚本

编写 bash 脚本有时候会很别扭和反直觉。例如 shellcheck 这样的工具可以帮助你定位sh/bash脚本中的错误。

man sh 查看 shell 的官方文档,可查到具体的使用技巧说明:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
set -e # 得脚本只要发生错误,就终止执行

在 Bash 脚本中,子 shell(使用括号 (...))是一种组织参数的便捷方式。
一个常见的例子是临时地移动工作路径,代码如下:
# do something in current dir
(cd /some/other/dir && other-command)
# continue in original dir

!! - 完整的上一条命令,包括参数
常见应用:当你因为权限不足执行命令失败时,可以使用 sudo !!再尝试一次

# && || ; 命令成功返回0,失败返回1
make && echo ok
which -a node || echo not found
command1 ; command2 # 多个独立的命令单独的顺序执行

^C SIGINT 中断:强行终止正在运行的程序
^D EOF 结束当前输入(即用户不再给当前程序发出指令),那么 Linux 通常将结束当前程序
^\ SIGQUIT 退出
^Z SIGTSTP:将一个正在前台执行的命令放到后台,并且处于暂停状态,不可执行

fg 将后台中的命令调至前台继续运行
bg 将一个在后台暂停的命令,变成继续执行(在后台执行)

^Z + bg:进程被移到后台运行,终端还能继续接受命令

执行脚本

注意脚本的执行环境可能带来的问题:当脚本在独立的子进程中执行时,无法直接访问父进程的 alias。 使用 source 或 . 而不是 ./script.sh 命令则在当前 shell 环境中执行,可以访问外部的 alias

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 重定向(stderr->stdout->file)
./script.sh >> output.log 2>&1 
./script.sh | tee output.log 2>&1

>&2 echo "The error was using magic numbers"

# 任务不随终端结束
# & 在后台运行,但当用户推出(挂起)的时候,发送SIGHUP信号,命令自动也跟着退出
script.sh &
# nohup 退出帐户/关闭终端之后继续运行相应的进程(一个忽略 SIGHUP 的封装)
nohup script.sh > log 2>&1

定时任务

crontab 默认在当前用户的主目录中执行命令,指定目录可以使用绝对路径或先 cd 进入工作目录。

系统在执行定时任务时不会加载任何环境变量,所以当脚本需要环境变量时,可以在 Crontab 文件的顶部添加一行 env 命令, 也可以在脚本中添加 source /etc/profile 命令来使配置生效(需要确保文件权限)

1
2
3
4
5
6
$ crontab -e # 编辑工作表 实际修改 /var/spool/cron/username
# 每隔 3 天的上午 8 点执行
0 8 */3 * * cd /home/usrname/campusnet && sh /home/usrname/campusnet/run.sh >> netloging.log 2>&1

$ crontab -l # 列出工作表里的命令
$ crontab -r # 删除工作作(小心使用)

环境变量

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 设置环境变量
# 临时
export UIMA_HOME="$(pwd)/apache-uima"
export PATH=$PATH:$UIMA_HOME/bin
# 永久
vim ~/.bashrc
export UIMA_HOME="/home/uname/Tools/apache-uima"
export PATH=$PATH:$UIMA_HOME/bin
export TREETAGGER_HOME='/home/uname/Tools/treetagger/bin'
export HEIDELTIME_HOME='/home/uname/Tools/heideltime-kit'
soucre ~/.bashrc

用户管理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 添加一个具有默认主目录的用户
useradd -m username
# 设置密码
passwd username

# 删除用户
userdel -r username

# 添加 sudo 权限
su          # change usr to root
visudo
---
# User privilege specification
root    ALL=(ALL:ALL) ALL
username ALL-(ALL:ALL) ALL  # add here

# 设置默认的shell
sudo chsh -s /usr/bin/zsh

离线安装

当无法使用包管理工具 sudo apt install package 直接安装时,可下载源码后手动编译完成安装,流程如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 从源码安装
apt-get source package
cd package
./configure --prefix=$HOME/opt/package
make
make install

# 从.deb包安装
apt-get download package
dpkg -i package.deb --force-not-root --root=$HOME

SSH 免密登录

免密登录的 原理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 1.local -> /Users/uname/.ssh/id_rsa
> ssh-keygen
> ll ~/.ssh
total 40
-rw-r--r--  1 uname  staff    86B Dec 23 11:12 config
-rw-------  1 uname  staff   2.6K Sep 24 22:06 id_rsa
-rw-r--r--  1 uname  staff   585B Sep 24 22:06 id_rsa.pub
-rw-------  1 uname  staff   2.1K Oct 24 22:05 known_hosts

> cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAXXXXX...

# 2.Add IdentityFile
> vim ~/.ssh/config
Host servername
  HostName xxx.xxx.xx.xx
  User uname
  IdentityFile /Users/uname/.ssh/id_rsa

# 3.remote: copy pub_key to remote
remote:~$ cd ~/.ssh/
remote:~/.ssh$ vim authorized_keys
# echo 你的公钥内容 >> ~/.ssh/authorized_keys

# 本地一条命令完成
cat .ssh/id_ed25519 | ssh foobar@remote 'cat >> ~/.ssh/authorized_keys'
# 或直接使用 ssh-copy-id
ssh-copy-id -i .ssh/id_ed25519.pub user@remote-ip
ssh-copy-id servername

# 完成
==> ssh servername

服务器代理

使用 clash 完成代理,打开 Allow Lan,配置代理ip: 本地ip,端口: clash 设置(deafult: 7890)

1
2
3
4
5
6
7
8
9
# 服务器上配置
vim ~/.bashrc
export http_proxy=http://xxx.xxx.xx.xx:7890
export https_proxy=http://xxx.xxx.xx.xx:7890
export ftp_proxy=http://xxx.xxx.xx.xx:7890
source ~/.bashrc

# test
curl www.baidu.com

Todo

  • sz/rz命令
  • fd -e jpg' 'find . -iname "*.jpg"'

Reference

0%