Linux 命令大放送!(第一辑)
涓涓细流,终汇大海。
在 "Shell 小技能" 一文中,讲到了 Shell 组合 linux 命令的实用小技能。每一条 linux 命令,都是一个小工具。 Shell 可以将很多小工具组合成更强大的实用工具。
本文主要梳理程序员常用到的 linux 命令。
文本命令
使用 lInux 命令处理临时任务,一大用场是文本处理。
文本命令模式,通常是通过 cat 获取文件内容,然后 grep 关键字 过滤出所需要的行,接着用 awk 或 cut 筛选列字段,最后用 sed 进行文本替换 或者 用 awk 格式化生成内容。文本处理的核心技能是正则表达式。
将值用引号括起来
orders.txt 是一个单列文本。每一行都是一个字符串值。
awk 'BEGIN{ORS=","}{print "\""$0"\""}' orders.txt
awk 'BEGIN{ORS=","}{print "\x27"$0"\x27"}' orders.txt
以下是提取日志关键字并构建数据库查询所需的 in 查询条件,常用于问题排查或线上故障后的数据修复。
cat webfileexist.txt | awk -F 'existDetectionId: ' '{print $2}' | grep -v "^$" | awk '{printf "%s%s", (NR>1?",":""), "\""$0"\""} END{print "]"}' | sed 's/^/[/'
筛选列并计数
给定文本格式:text1 = text 2 = 数值,输出满足某种条件的行或列并计数。
file=$1
total=`wc -l $file`
echo "total: $total"
avg=`cat $file | cut -f 3 -d'=' | awk '{a+=$1}END{print a/NR}'` // 求平均值
echo "avg: $avg"
above_num=`cat $file | cut -f 3 -d'=' | awk '{if ($1>=100) print $1}' | wc -l` // 找到大于 100 的行的计数
above_percent=`echo "$above_num $total" | awk '{printf("%0.1f%%\n",100*$1/$2)}'`
echo "more than 100ms percent: $above_percent"
筛选列并用空格分割输出
将 order.txt 的第一列和第二列输出,用空格符分割。
awk -F" " '{print $1" "$2}' order.txt
提取JSON 字符串中的指定字段的值
每一行都是:
{"level":"info","time":"2024-04-07T10:50:44.369Z","caller":"scheduler/cdc_check_task_execute_scheduler.go:131","msg":"build cdc task msg","tenantID":"","method":"(*CdcCheckTaskScheduler).buildTaskMsg","msg":{"fileId":"xxx","md5":"6debc533d08caa6181e2aa2b5682d6b7","sha256":"966d3230586dc211de801a229e333074f5ae7f1082779316ee4b9fadb60c14dd","fileSize":194,"fileType":"PHP","isZip":false,"timeout":300,"engineVersion":"2.5"}}
需要安装 jq 命令。
grep "sha256" cdc_send_messages.txt | jq -r '.msg.sha256'
grep "sha256" cdc_send_messages.txt | jq -r '.msg.sha256' | sort | uniq -d | wc -l
提取字符串
cat xxx.txt | grep -P "field=[a-zA-z]+" -o
cat xxx.log | grep -E "([0-9A-Z]+-)*[0-9A-Z]+" -o
排序去重
cat a.txt | sort | uniq
find . -name "*.java" > /tmp/javafile.txt && sed -E 's?^\./.+/([a-zA-Z]+\.java).*$?\1?g' /tmp/javafile.txt | sort | uniq -d
日志查看
zcat sys.log.5.gz |grep webshell_detection
tail -100f info.log | grep "method="
grep -E "A|B" info.log
ls info.20220616.* | xargs -I {} grep "cdcCheckCache hit is black" {} > /home/blackhit.log
ls info.20220615.* | xargs -I {} grep "send webshell cdc task to kafka, size" {} | cut -f 5 -d ":" | sed 's/^[ \t]*//g' | awk '{sum += $1};END {print sum}'
grep -r "cdcCheckCache hit is black" info.20220616.*
字符替换
cat a.sh | tr -s "a" "c"
cat a.sh | tr "a-z" "A-Z"
cat a.txt | tr -s "," "\n"
cat a.txt | tr -s "\n" " "
sed 替换
sed "s/old/new/g" a.sh // 不会改变 a.sh,
sed -i "s/old/new/g" a.sh // 直接将 a.sh 中的 old 全部替换成 new ,改变 a.sh
sed -E 's?^\./.+/([a-zA-Z]+\.java).*$?\1?g' javafiles.txt // 提取匹配 [a-zA-Z]+\.java 的内容
cat md.txt | sed -e 's/\(#\{1,\}\)$/\<br\/\>/g ; s/^\(#\{1,\}\)/\<br\/\> \1 /g'
sed -i -e 's/\(#\{1,\}\)$/\<br\/\>/g ; s/^\(#\{1,\}\)/\<br\/\> \1 /g' md.txt
sed -i -e 's/\(#\{1,\}\)$//g ; s/^\(#\{1,\}\)/\<br\/\> \1 /g' md.txt
// 在 port 下加一行
sed -i '/^ *port:.*/a\ serviceExecutor: adaptive' net.txt
// 去掉空行
sed '/^$/d' roujia.txt | tr '\n' ' ' | sed 's/ //g'
文件命令
文件命令是 linux 日常任务处理的第二大用武之地。
通常的做法是,是先用 find 命令筛选出符合条件的文件集合,然后结合 xargs 或 while 循环,和其它文件命令进行批量处理。
查找和删除文件
find ~/[0-9]* -name "*.csv" -mtime +29 -type f | while read file; do rm -f $file; done
find . -size +100M | xargs -I {} ls -hl {}
文件Hash
md5 /tmp/hello.txt
shasum -a 1 /tmp/hello.txt
shasum -a 256 /tmp/hello.txt
文件链接
ln
ln -s 要被链接的文件(已存在) 新的链接文件(不存在)
ln -s 源文件 目标链接文件
ln -s /usr/local/go/bin/go /usr/local/bin/go
修改文件权限
ls -d BEAUTYPIC2000* | xargs -I {} chmod 744 {}
文件拷贝
文件拷贝是日常任务处理的一个高频操作。务必要熟练掌握。
从 k8s pod 到宿主机
kcp.sh
#!/bin/bash
# cp files in k8s pod container to k8s host
# 指定Pod名称
POD_NAME=$(kubectl get po -A | grep xxx | awk '{print $2}')
NAMESPACE=$(kubectl get po -A | grep xxx | awk '{print $1}')
# 指定容器名称,默认为Pod的第一个容器
CONTAINER_NAME=main
# 指定宿主机上存放文件的目录
HOST_DIR="/tmp"
# 拷贝文件
kubectl exec ${POD_NAME} -n $NAMESPACE -c ${CONTAINER_NAME} -- bash -c 'cp /tmp/ids_method_costs_*.txt /workspace/ && ls /tmp/ids_method_costs_*.txt' | \
while read -r FILE; do
FILENAME=$(basename ${FILE})
HOST_FILE="${HOST_DIR}/${FILENAME}"
echo "kubectl cp ${POD_NAME}:${FILE} -n $NAMESPACE -c ${CONTAINER_NAME} ${HOST_FILE}"
kubectl cp ${POD_NAME}:${FILE} -n $NAMESPACE -c ${CONTAINER_NAME} ${HOST_FILE}
done
宿主机文件拷贝
bscp.sh
#!/bin/bash
# copy files in host A to local host
# 指定宿主机A的IP地址和登录凭证
HOST_A="someip"
USER_A="root"
PASSWORD_A="qingteng"
# 指定宿主机B上存放文件的目录
HOST_B_DIR="/Users/qinshu/Development/"
# 指定宿主机A上存放文件的目录
HOST_A_DIR="/tmp/"
file_list=$(sshpass -p ${PASSWORD_A} ssh ${USER_A}@${HOST_A} "ls ${HOST_A_DIR}/ids_method_costs_*")
# 拷贝文件
for file in ${file_list}; do
filename=$(basename ${file})
echo "sshpass -p ${PASSWORD_A} scp ${USER_A}@${HOST_A}:${file} ${HOST_B_DIR}/${filename}"
sshpass -p ${PASSWORD_A} scp ${USER_A}@${HOST_A}:${file} ${HOST_B_DIR}/${filename}
done
拷贝文件
kubectl cp -n $(kubectl get po -A | grep ids-detect | awk '{print $1}') -c main $(kubectl get po -A | grep ids-detect | awk '{print $2}'):dump.hprof /tmp/dump.hprof // pod => k8s
kubectl cp /root/arthas-client.jar -c main $(kubectl get po -A | grep ids-detect | awk '{print $1}')/$(kubectl get po -A | grep ids-detect | awk '{print $2}'):/workspace // k8s => pod
scp root@172.16.13.40:/tmp/dump.hprof ~/Documents // scp remote => local
本地拷贝文件和目录
cp file dir
cp -r files dir
cp -r src_dir dest_dir // => dest_dir/src_dir
cp -r src_dir/* dest_dir // => dest_dir/[aa.txt, sub]
cp -r files src/* dest // => dest_dir/[files, aa.txt, sub]
cp -r files src2_dir src/* dest // => dest_dir/[files, src2_dir, aa.txt, sub]
rm -rf dest/* # 删除 dest 下的所有目录和文件,但是不删除 dest 目录本身
远程主机间拷贝
scp file user@ip:dir
scp user@ip:dir file
scp -r eventflow-lib/1.0.0-RELEASE root@someip:/pathto/deploy/repository/com/common/eventflow-lib
批量处理
批量处理增强了 linux 命令处理的威力。
批量处理通常采用 xargs 命令。使用起来也比较简单,就是占位符模式。比如一个命令是 rm -rf somefile, 用 xargs 命令批量处理就是 xargs -I {} rm -rf {}。
批量复制/删除文件
find . -name "*.java" | xargs -I {} cp {} /tmp
find . -name "*.java" | xargs -I {} rm -rf {}
批量执行命令
以下命令先将 tt.py 通过替换文本 tt 为随机值的方式复制 3 个文件,然后找到所有 .py 文件,在 cmd.txt 批量写入命令 python3 xxx.py ,最后并发执行 cmd.txt 里的命令。
go run copy.go -n 3 -f tt.py -r tt && find . -maxdepth 1 -name "*.py" | xargs -I {} echo "python3 {}" > cmd.txt && go run multi_run.go -f cmd.txt
批量杀死符合关键字的进程
bkill.sh
#!/bin/bash
ps aux | grep "$1" | awk '{print $2}' | xargs -I {} sudo kill -9 {}
使用
chmod +x bkill.sh
./bkill python
批量截取列
## 批量处理
```bash
cat a.txt | xargs -I {} grep {} xyz.log | grep "key" | cut -f 2- -d'='
杀进程
杀死占用 80 端口的进程
注意:必须加 sudo 才会展示进程PID。
sudo netstat -lnp | grep :80
sudo kill -9 pid
源代码编译
很多 linux 开源软件,如果没有提供二进制包,就可以用如下三步轻松构建和生成可执行的二进制文件,将源代码变成实用软件。
./configure
make
make install
格式编码转换
图片格式转换
dwebp file.webp -o abc.png
find ./ -name "*.webp" -exec dwebp {} -o {}.png \;
ffmpeg -i file.webp out.png
编码转换
虽然很多时候有更好的图形界面来做音图视频编码或格式转换,但掌握一些命令,或许在特定场景下会更加高效。比如说视频剪切,我发现比图形界面快很多。
iconv -f gb18030 -t utf-8 origin.csv > new_utf8.csv // GB18030 转码为 utf8
iconv -f utf-8 -t gb18030 batch_express.csv > upload.csv // utf8 转 GB18030
ffmpeg
ffmpeg -i aa.rmvb -c:v libx264 -strict -2 aa.mp4 // 视频格式转换
视频剪切
ffmpeg -ss 00:00:00 -i xxx.avi -to 00:53:20 -c copy xxx.mp4
ffmpeg -ss 00:00:00 -i xxx.avi -to 00:53:20 -c copy -copyts xxx.mp4
ffmpeg -ss 00:00:00 -i MANCHENGFENGXU00116.mov -t 270 -c copy MANCHENGFENGXU00116c1.mp4
ffmpeg -i shengongyimeng.mp4 -ss 00:59:20 -to 01:03:17 -c copy shengongyimengc1.mp4
音频转换
ffmpeg -i inputfile.m4a -acodec libmp3lame -ab 93k outputfile.mp3
视频压缩
ffmpeg -i MANCHENGFENGXU00116c1.mp4 -y -vcodec libx264 -preset fast -b:v 5120k -vf scale=1600:1200,setdar=3:4 MANCHENGFENGXU00116c1ys.mp4
-b:v :指定视频的码率
-b:a : 指定音频的码率
1M:码率的值 1M 表示 1Mb/s
-r 20:表示帧率设置为 20fps
-vf scale=1600:1200表示分辨率为1600*200
ls *.mov |while read id;do (ffmpeg -i "$id" -y -vcodec libx264 -preset fast -b:v 5120k -vf scale=1600:1200,setdar=3:4 "${id%%.*}.mp4" );done
加密
gzexe : 加密可执行文件
gzexe a.sh
gzexe -d a.sh
tar + openssl
对filename文件(test.txt)进行加密压缩,生成filename.des3加密压缩文件,123@123为加密的密码
tar -zcf - test.txt | openssl des3 -salt -k 123@123 | dd of=test.txt.des3
将/mnt目录下的所有文件全部加密压缩
tar -zcf - /mnt/* | openssl des3 -salt -k 123@123 | dd of=test.des3
模拟匹配加密压缩
tar -zcf - /mnt/pass_* |openssl des3 -salt -k 123@123 | dd of=test.des3
解压解密:
dd if=test.txt.des3 | openssl des3 -d -k 123@123 | tar zxf -
加密:
tar -czf - * | openssl enc -e -aes256 -out test.tar.gz
enc 使用加密进行编码
-e 用来加密输入文件的 enc 命令选项,这里是指前一个 tar 命令的输出
-aes256 加密用的算法
-out 用于指定输出文件名的 enc 命令选项,这里文件名是test.tar.gz
解密:
openssl enc -d -aes256 -in test.tar.gz | tar xz -C /mnt/
-d 用于解密文件
-C 将加压后的文件提取到目标目录下
shc :脚本加密
shc -r -f text.sh
# 加过期时间
shc -e 28/02/2018 -m "this script file is about to expire" -v -r -f text.sh
zip 加密
zip -e filename.zip filename
zip -re dirname.zip dirname
GnuPG加密
gpg -c test.txt
网络命令
ping & telnet & tracert
ping www.baidu.com -c 4
telnet www.baidu.com 80
tracert www.baidu.com
route
linux: route -n
mac: netstat -nr
tcpdump 抓包
tcpdump -vv -i any -nn port 20881 -A
net config
sudo sysctl -a > ~/netconfig.txt
ports listener
sudo netstat -anp | grep port
ufw & iptables
sudo ufw enable | disable
sudo ufw status
sudo ufw default deny
sudo ufw allow 22/tcp
sudo ufw allow proto udp 192.168.0.1 port 53 to 192.168.0.2 port 53
iptables -nvL
iptables -F (flush 清除所有的已定规则)
iptables -X (delete 删除所有用户“自定义”的链(tables))
磁盘命令
磁盘相关的问题通常是磁盘空间不够了。想知道哪些资源占用磁盘空间大,以下命令很有效。
找到占用空间大的目录
sudo du -s -h /*
sudo du -s -h /var/lib/* | grep G
发现是 /var/lib/docker/overlay2 占用太大。使用
docker system prune
当前目录下的占用空间情况
du -ahx | sort -rh | head -5
du -d 1 -h | sort -rh | head -20
du -ah /var/ | sort -rh | head -10
du -hl --max-depth=1
du -hsx * | sort -rh | head -10
du -hsx .[^.]* | sort -rh | head -10
du -ah /data/ | grep G
df -h
du -h ~ | grep 'G'
du -h /dev/vda1 | grep 'G'
判断是否ssd
开发中,有些 IO 要求高的软件运行性能,会要求 SSD 盘。
cat /sys/block/vda/queue/rotational # 1 固态硬盘
lsblk -d -o name,rota #0 固态硬盘
在Linux系统中,可以使用以下命令来判断磁盘是否为SSD:
lsblk -d -o name,rota
该命令会列出所有磁盘的名称和旋转标志。如果旋转标志为0,则表示该磁盘是固态硬盘(SSD),如果旋转标志为1,则表示该磁盘是机械硬盘(HDD)。
另外,也可以使用以下命令来查看指定磁盘的详细信息,包括磁盘类型:
hdparm -I /dev/sda | grep "Model\|Firmware\|TRIM\|Rotation\|Transport\|SATA\|Form Factor"
其中,“/dev/sda”是要查询的磁盘设备文件名。如果输出结果中包含“Solid State Device”等字样,则表示该磁盘是固态硬盘(SSD)。
需要注意的是,以上命令都需要root权限才能执行。
安装软件
# ubuntu/debian
sudo apt-get install
sudo apt-get update
sudo apt-get remove
sudo dpkg -i xxx.deb
# centos
wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
yum install epel-release-latest-7.noarch.rpm
yum install -y nc
# linux
wget some_url | bash
系统服务
sudo service apache2 start
sudo service apache2 stop
sudo service apache2 status
sudo systemctl start NetworkManager
sudo service apache2 stop
sudo systemctl status NetworkManager