Skip to main content

Linux 简单有趣的命令

作草分茶About 10 min

Linux 简单有趣的命令

本文不定期更新。

网络命令

nc tcp连接工具

nc 可以建立 TCP 连接

nc localhost 6379

连接后可以执行命令

set name jonkee
+OK
get name
$6
jonkee

telnet 端口测试

telnet mycloud 3306

ssh & sshpass 服务器连接

生成密钥对

# -t 指定加密算法
# -b 指定密钥的二进制位数
# -C 注释
ssh-keygen -t rsa -b 4096 -C "qiqiangvae@foxmail.com"
# 查看生成的密钥对
ls ~/.ssh/

上传公钥。也可以在服务器上创建一个~/.ssh/authorized_keys文件,并修改权限为664,然后在将本地客户端内id_rsa.pub的内容复制进去。

# -i 指定公钥文件
ssh-copy-id -i ~/.ssh/id_rsa.pub username@host

ssh 命令可以连接服务器,但是连接服务器的时候要输入密码,而sshpass可以免去手动输入密码的操作。

ssh -p 22 {username}@{ip}
sshpass -p {password} ssh -p 22 {username}@{ip}

ssh 还可以实现跳板机隧道功能。

如本机 Local 想要访问 ServerPort 端口,但是 Server 是在内网,无法访问,但是跳板机 Jump 可以访问 Server,而 Local
可以访问跳板机,此时可以使用ssh实现隧道功能。

# 要输入 jump 跳板机密码
ssh -N -f -L {localPort}:{ServerIP}:{ServerPort} {JumpUsername}@{JumpIP}
# 使用sshpass免去输入跳板机密码过程
sshpass -p {JumpPass} ssh -N -f -L {localPort}:{ServerIP}:{ServerPort} {JumpUsername}@{JumpIP}

此时连接 Local 的 localPort 就可以连接上 Server 的 ServerPort 了。

通过跳板机连接服务器,然后依次输入跳板机和服务器的密码。

ssh {ServerUsername}@{ServerIP} -p 22 -o ProxyCommand='ssh -p 22 {JumpUsername}@{JumpIP} -W %h:%p'

curl 网络请求客户端

curl 命令可以用来发送 web 请求。

# 发送 get 请求
curl https://www.baidu.com
# 头信息
curl -H 'Authorization:my-token' https://www.baidu.com
# 发送 cookie
curl -b 'name=muan;sex=1' https://www.baidu.com
# 存储响应 cookie
curl -c resp_cookie.txt https://www.baidu.com
# 发送 POST 请求
curl -X POST -d '{"username":"user","password":"pass"}' https://xxx.com/login
# 保存响应信息
curl -o resp.txt https://www.baidu.com
# 获取响应头
curl -I https://www.baidu.com
使用符号说明
代理头-AUser-Agent
请求头-HHeader
发送 cookie-b
存储响应 cookie-c
发送 body-d
指定 Http 请求方式-X
打印响应头和内容-i
仅仅打印响应头-I大写的 i
保存响应信息-o

scp 服务器间复制文件

在服务器之间复制文件和目录。scp fileName user@ip:fileName2

# 将 demo.log 复制到服务器的 /home/dc2-user 目录下
scp demo.log dc2-user@mycloud:/home/dc2-user

如果是复制目录,则需要加上参数-r

masscan & nmap 端口扫描

masscan 和 nmap 都可以扫描服务器开放的端口,nmap 可以扫描域名,masscan不可以。masscan 扫描速度比 nmap 快很多。

sudo masscan -p1-65535 xxx.xxx.xx.xxx
sudo nmap -sS -Pn -p1-65535 www.baidu.com

tcpdump 抓包工具

tcpdump 命令可以抓取指定网卡的指定ip和端口的数据包。

tcpdump -A dst xxx.xxx.x.xxx and port 3306 -w redis_dump.dump

文本命令

xargs 参数转换

xargs 的作用是将标准输入转为命令行参数。

简单的案例

echo "1.txt 2.txt 3.txt" | xargs touch

使用 xargs 批量删除redis key。以下命令的意思是,先找出所有的 key,然后通过 xargs 命令将结果用空格分开,然后删除。

redis-cli -a password -h localhost -p 6379 keys "*" | xargs redis-cli -a password -h localhost -p 6379 del

默认情况下 xargs 会将输入用空格或者换行符分割,也可以用 -d 指定分割符。

# -e 表示解释转义字符
echo -e "韩信\t李白\t百里守约" | xargs -d "\t" echo

输出

韩信 李白 百里守约
参数解释
-p打印需要执行的命令,询问是否执行,输入y或Y确认
-t打印需要执行的命令,不需要用户确认

awk 文本coding

  1. 每行按空格或TAB分割,输出文本中的1、4项;

    awk '{print $1,$4}' log.txt
    
  2. 输出 java 进程的 pid;

    ps -ef|grep java|awk '{print $2}'
    

    输出

    67396
    69344
    75192
    
  3. -F 指定分隔符;

    # -F 指定分隔符为 =
    awk -F '=' '{print $1,$2}' file.txt
    
  4. -v 设置变量;

    awk -F '=' -v p=2 '{print $1,$2,$2+p}' file.txt
    
  5. 指定列;

    # 只输出第列的值等于2的行
    awk -F '=' '{if ($2 == 2) print $1,$2}' file.txt
    # 指定多个分隔符,如 |$|
    awk -F '[|][$][|]' '{if ($2 == 2) print $1,$2}' file.txt
    
  6. 去重;

    # 按=分割并去重
    awk -F '=' '{print $3}' filename |awk '!a[$0]++'
    
  7. 分组;

    # 多个分隔符,并按字段分组找出所有个数大于 1 的
    awk -F '[|][$][|]' '{count[$10]++;} END {for(i in count) { if (count[i]>1){print i,count[i]}}}' filename
    

    NF 代表当前行有多少个字段,即 NF-1代表倒数第二个字段。
    NR 代表当前行数。

    相关函数:

函数说明
length(str)返回字符串 str 的长度。
substr(str, start, length)返回字符串 str 从 start 开始,长度为 length 的子串。
split(str, arr, sep)把字符串 str 以分隔符 sep 分割成若干个部分,并将它们存储到数组 arr 中。
gsub(regexp, replacement, str)在字符串 str 中,用 replacement 替换所有匹配到的正则表达式 regexp。
sub(regexp, replacement, str)在字符串 str 中,用 replacement 替换第一个匹配到的正则表达式 regexp。
index(str, substr)查找字符串 str 中的子串 substr 第一次出现的位置。如果没有找到,则返回 0。
tolower(str)将字符串 str 转换成小写字母。
toupper(str)将字符串 str 转换成大写字母。
sprintf(format, expr1, expr2, ...)类似于 C 语言中的 sprintf() 函数,用于格式化输出。
rand()返回一个 0 到 1 之间的随机数。

grep 过滤神器

  1. -C 10 或者 --context=10 显示前后 10 行的内容;

  2. -A 10 或者 --after-context=10 显示之后 10 行的内容;

  3. -B 10 或者 --before-context=10 显示之前 10 行的内容;

  4. -v 显示不匹配的(忽略匹配的,即取反);

  5. -n 显示行号;

    grep -n 'search_txt' filename
    

split 文件分割

  1. 按行分割,比sed命令截取好用;

    split -l 1000 data.csv prefix
    
  2. 按大小分割;

    split -b 1000 data.csv prefix
    

sed 文本编辑命令

注意

注意-i是在源文件修改,-e是输出到控制台,如果是修改源文件,需要加上备份文件的后缀,如果不想备份,输入空字符串。

  1. 替换字符串

    sed 's/原字符串/替换字符串/g'
    
  2. 替换指定行

    # 替换第10行的文本
    sed '10c hello world' filename	
    
  3. 删除行

    # 删除第 10 行
    sed -i '.bak' '10d' filename
    # 删除第 10-20 行
    sed -i '.bak' '10,20d' filename
    
  4. 截取行数

    # 截取第1行到第10行
    sed -n '1,10p' filename
    # 截取第1行到第10行并输出到另一个文件
    sed -n '1,10p' filename > new_filename
    # 截取第11行到文件末尾并输出到另一个文件中
    sed -n '11,$p' filename > new_filename
    

wc 文本统计

  • -c 或 --bytes 或 --chars 只显示 Bytes 数。
  • -l 或 --lines 显示行数。
  • -w 或 --words 只显示字数。
wc -l filename

wc -l命令时发现少了一行

如果在使用 wc -l 命令时发现少了一行,请注意以下几个问题:

  1. 换行符问题:wc 命令计算行数时,是根据换行符来判断的。如果您的文件最后一行没有以换行符结尾,那么 wc -l 命令就会将该行计算为不完整的一行,从而导致行数少一行。
  2. 文件编码问题:如果您的文件是以 Unicode 编码(如 UTF-8)保存的,并且文件头部没有明确指定编码格式,则 wc -l 命令可能会误判换行符的位置,导致行数计算错误。
  3. 行尾空格问题:如果您的文件最后一行有多余的空格或制表符,那么 wc -l 命令就会将这些空格或制表符也计算为一行的内容,从而导致行数计算错误。

如果您遇到了以上问题,可以尝试以下解决方案:

  1. 检查文件是否以换行符结尾,如果没有,请添加一个换行符。
  2. 如果文件使用 Unicode 编码,请在文件头部添加明确的编码格式,例如 # -- coding: utf-8 --。
  3. 检查最后一行是否有多余的空格或制表符,如果有,请删除它们。

vim 快捷键

按键功能
h 或者 ←向左移动
j 或者 ↓向下移动
k 或者 ↑向上移动
l 或者 → 或者空格向右移动
[n]+空格向右移动 n 格
[n]+方向向某个方向移动n次
ctrl+f向下翻页
ctrl+b向上翻页
0 或者 home移动到该行的第一个字符处
$ 或者 end移动到该行的最后一个字符处
G移动到最后一行
H移动到第一行
[n]G跳转到第 n 行
/key向下搜索关键字
?key向上搜索关键字
n 或者 N根据/key或者?key的方向重复查找某个关键字。n和N方向相反
x 或者 Xx 向后删除,X 向前删除
[n]x连续删除
dd删除当前光标所在行
[n]yy复制一(多)行
p粘贴
:w [filename]另存为
:%d清空所有的内容

压缩命令

tar

-z 表示 gzip,-c压缩,-x解压,-v显示过程。

# 从文件 foo 和 bar 创建归档文件 archive.tar。
tar -cf archive.tar foo bar  
# 详细列举归档文件 archive.tar 中的所有文件。
tar -tvf archive.tar         
# 展开归档文件 archive.tar 中的所有文件。
tar -xf archive.tar   
# 解压到指定文件夹
tar -xf archive.tar -C targetDir

系统命令

其它命令

nohup 不挂断运行

no hang up 不挂断。

nohup command > myout.log 2>&1 &  
  • 0 标准输入;

  • 1 标准输出;

  • 2 标准错误;

2>&1 是将标准错误2重定向到标准输出&1&1再重定向到myout.log中。

编写一个脚本nohup_demo.sh循环打印。

count=0
while [ $count -lt "100" ]; do
    echo 'hello muan'
    sleep 1s
    count=$(expr $count + 1)
done

测试

# 启动
$ nohup sh nohup_demo.sh > demo.log 2>&1 &
80306
# 查看日志
$ tail -f demo.log
hello jonkee
hello jonkee
hello jonkee
hello jonkee
# 停止
$ kill -9 80306

mv 命令冷知识

mv 命令可以用来移动文件和改名,那么什么时候是移动文件什么时候是改名呢

# 新建两个文件夹
$ mkdir d1 d2
# 在d1里面新建两个文件
$ touch d1/f1 d1/f2
# 将d1改为d3
$ mv d1 d3
$ ls d3
f1  f2
# 将d3移入d2
$ mv d3 d2
$ ls d2/d3/
f1  f2

为什么最后一个命令不是将 d3 改名为 d2 呢?因为d2目录已经存在来,所以不会改名。

总结:目标文件不存在则改名,目标文件存在则移动。

tldr 最好用的命令文档

这个命令是Too Long; Didn't Read的缩写,这个名字很有趣

# mac 安装
brew install tlrc
# npm 安装
npm install -g tldr
# pip
pip3 install tldr

安装好之后可以查看命令,比如

tldr curl
  curl

  向 / 从一个服务器传输数据。
  支持大多数协议,包括 HTTP, FTP, 和 POP3.
  更多信息:https://curl.se/docs/manpage.html.

  将指定 URL 的内容下载到文件:

    curl http://example.com --output 文件名

  将文件从 URL 保存到由 URL 指示的文件名中:

    curl --remote-name http://example.com/filename

  下载文件,跟随 重定向,并且自动 续传(恢复)前序文件传输:

    curl --fail --remote-name --location --continue-at - http://example.com/filename

  发送表单编码数据(application/x-www-form-urlencoded 的 POST 请求):

    curl --data 'name=bob' http://example.com/form

  发送带有额外请求头,使用自定义请求方法的请求:

    curl --header 'X-My-Header: 123' --request PUT http://example.com

  发送 JSON 格式的数据,并附加正确的 Content-Type 请求头:

    curl --data '{"name":"bob"}' --header 'Content-Type: application/json' http://example.com/users/1234

  使用用户名和密码,授权访问服务器:

    curl --user 用户名 http://example.com

  为指定资源使用客户端证书和密钥,并且跳过证书验证:

    curl --cert client.pem --key key.pem --insecure https://example.com

简单的脚本案例

循环读取文件每一行并处理

无法读取最后一行

[[ -n ${line} ]]加上这个判断是为了解决最后一行无法读取的问题

cat field.txt| while read line || [[ -n ${line} ]];
do
  echo '- value:' $line
done