便捷shell,shell小技巧

本文分享了一系列Shell脚本的小技巧,包括系统信息查询、登录与免密操作、数学运算、进程管理和网络操作等。这些技巧可以帮助提高日常工作效率,适用于系统管理员和开发人员使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

系统查看:

测试CPU是小端序还是大端序:

#1为小端模式,0为大端模式
echo -n I | od -o | head -n1 | awk '{print $2}'| cut -c6

#或通过lscpu命令,显示 Little Endian / Big Endian
lscpu | grep 'Byte Order'

查看CPU是32位还是64位:

#显示架构名称,如x86_64、ppc等
uname -m

#或通过lscpu命令显示架构名称
lscpu | grep 'Arch'

查看设备制造商:

lspci
#05:00.2 Encryption controller: Device 1d94:1456
#厂商:1d94
#型号:1456

然后在网站查询:

Find unknown devices using a vendor and device ID. | Device Hunt

Device Knowledge Base - Device KB

----

登录与免密:

免密登录:

#安装sshpass
yum install -y sshpass
#命令行
sshpass -p 'mypassword' ssh myusername@10.0.0.1 -p 22
#命令行+环境变量
export SSHPASS=mypassword
sshpass -e ssh myusername@10.0.0.1 -p 22

windows进入bash环境:

bash.cmd:

@echo off
if not exist bashrc.sh (
	rem 8行之后的内容写入文件
    more +8 %0 > bashrc.sh
)
"D:\Program Files\Git\bin\bash.exe" --rcfile bashrc.sh

rem 本行之后写入文件
# ~/.bashrc
export LC_ALL="zh_CN.UTF-8"
export LANG="zh_CN.UTF-8"
alias ll="ls -lh"
##or
#echo 'ls -lh $*' > /usr/bin/ll
cd /d/

临时禁用history记录,缺点是无法使用上翻命令的功能了:

# HISTSIZE 表示对于 bash 会话历史列表中可以保存命令的个数(行数),默认值为 1000。
# 在这个命令之前的所有记录都会原样保留在历史列表中。
# 这条命令不会被记录,之后的命令也不会被记录。
# 恢复设置使用:export HISTSIZE=1000,这条命令不会被记录,之后的命令会被记录。
export HISTSIZE=0

# 或使用

# 在这个命令之前的所有记录都会原样保留在历史列表中。
# 这条命令会被记录,之后的命令不会被记录。
# 使用 set -o history 恢复,这个命令不会被记录,之后的命令会被记录。
set +o history

清除本次会话的history历史记录,之前的历史记录原样保留:

# 本条命令不会被记录,本次登录前的历史记录会保留,清楚本次登录会话的记录。
history -cw

让history记录时间:

export HISTTIMEFORMAT='%F %T '

----

数学运算:

16进制数字转10进制:

#16进制转10进制
((num=0x11)); echo $num

#10进制转16进制
echo "obase=16;17"|bc

----

进程操作:

根据进程名使用进程pid,如果多个进程用空格分割pid:

echo `ps aux | grep ProcName | grep -v 'grep' | awk '{print $2}'`

echo `pgrep ProcName`

根据进程名使用多个进程pid,多个进程用-p分割pid:

echo `ps aux | grep ProcGroupName | grep -v 'grep' | awk '{print "-p " $2}'`

echo `pgrep ProcGroupName | awk '{print "-p " $1}'

非交互使用top,显示某个进程的信息3次,然后退出:

top -b -n 3 -p $pid

通过pid等待某个进程结束:

tail --pid=$pid -f /dev/null
#或
lsof -p $pid +r 1 &>/dev/null

shell同时运行两个进程:

sleep 111 & sleep 222

shell先后运行两个进程:

sleep 333 && sleep 444

调低进程调度优先级:

renice -n 19 -p `pidof $prog_name`

shell模拟wait子进程,shell循环判断进程是否退出了:

if [ "$1" == "" ]; then
    processName=sleep
else
    processName=$1
fi
while true; do
    ps -ef | grep $processName |grep -v grep &> /dev/null
    if [ "$?" != "0" ];then
        echo `date` "all $processName exited"
        break
    fi
    sleep 1
done

排查系统内存占用最高的进程:

#查看内存占用过高的进程
ps -aux | sort -k4nr | head -n 5

#查看进程内存占用情况
ps aux --sort=-%mem

#查看是否存在未被释放的进程
sudo lsof | grep deleted

将shell脚本的输入输出重定向到文件:

#!/bin/bash
#exec会启动一个新shell并将stdout文件描述符重定向到文件。
exec 1>stdout.log

#!/bin/bash
#exec会启动一个新shell并将stderr文件描述符重定向到文件。
exec 2>stderr.log

#!/bin/bash
#告诉shell它应该从文件stdin.txt中获得输入,而不是stdin。
exec 0<stdin.txt

#!/bin/bash
#exec命令将文件描述符3重定向到另一个文件。
exec 3>myout.log

#!/bin/bash
#exec会启动一个新shell并同时重定向stdout和stderr。
exec 1>stdout.log 2>stderr.log

#!/bin/bash
#exec会启动一个新shell并将stdout追加到文件。
exec 1>>out-append.log

----

网络操作:

获取本机ipv4地址:

echo `ip a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"|head -1|cut -d / -f 1`

通过路由转发树获取本机IP:

awk '/32 host LOCAL/ { print i } {i=$2}' /proc/net/fib_trie | grep -v '127.0.0.1' | sort | uniq

获取默认出口网卡设备名:

cat /proc/net/route | cut -f 1,2 | grep '00000000' | cut -f 1

查看物理网卡和虚拟网卡:

[work@localhost ~]$ sudo lspci | grep Ethernet
3d:00.0 Ethernet controller: Intel Corporation Ethernet Connection X722 for 1GbE (rev 09)
3d:00.1 Ethernet controller: Intel Corporation Ethernet Connection X722 for 1GbE (rev 09)
3d:00.2 Ethernet controller: Intel Corporation Ethernet Connection X722 for 1GbE (rev 09)
3d:00.3 Ethernet controller: Intel Corporation Ethernet Connection X722 for 1GbE (rev 09)
[work@localhost ~]$ sudo ls -lh /sys/class/net/
总用量 0
lrwxrwxrwx 1 root root 0  3月 18 13:58 lo -> ../../devices/virtual/net/lo
lrwxrwxrwx 1 root root 0  3月 18 13:58 p9p1 -> ../../devices/pci0000:3a/0000:3a:00.0/0000:3b:00.0/0000:3c:03.0/0000:3d:00.0/net/p9p1
lrwxrwxrwx 1 root root 0  3月 18 13:58 p9p2 -> ../../devices/pci0000:3a/0000:3a:00.0/0000:3b:00.0/0000:3c:03.0/0000:3d:00.1/net/p9p2
lrwxrwxrwx 1 root root 0  3月 18 13:58 p9p3 -> ../../devices/pci0000:3a/0000:3a:00.0/0000:3b:00.0/0000:3c:03.0/0000:3d:00.2/net/p9p3
lrwxrwxrwx 1 root root 0  3月 18 13:58 p9p4 -> ../../devices/pci0000:3a/0000:3a:00.0/0000:3b:00.0/0000:3c:03.0/0000:3d:00.3/net/p9p4
[work@localhost ~]$ sudo ls -lh /sys/devices/virtual/net/
总用量 0
drwxr-xr-x 5 root root 0  3月 18 13:58 lo
[work@localhost ~]$ 

curl post文件内容,且替换某些字段的取值:

params=""
while read -r line
do
        line=`echo $line | tr "\n" " " | tr "\r" " "`
        params=$params$line
done < ./params_file.json

datestr=$(date "+%Y%m%d%H%M%S")
params=${params//trace_id/$datestr}
#params=${params//\"/\\\"}
echo $params

curl -k '127.0.0.1:8080/my_url' -H "Content-type: application/json" -H "token: xxx" -plaintext -d "$params"

查看局域网内不可达的ip:

find_unreachable_ip_in_lan.sh:

#!/bin/sh

if [ "$1" != "" ]; then
	lan_prefix=$1
else
	lan_prefix="10.10.10"
fi

for ((i=2; i<255; i+=1))
do
	ip="$lan_prefix.$i"
	exists=`ping -c 2 $ip | grep -i Unreachable | wc -l`
	if [ "$exists" != "0" ]; then
		echo $ip
	fi
done

----

字符串操作:

将字符串用空格分割并取第2、3、4个字段:

echo $str | cut -d ' ' -f 2,3,4

将字符串用空格分割并取最后一个字段:

echo $str | rev | cut -d ' ' -f 1 | rev

将字符串用空格切分为数组用于for循环:

echo "1 2 3" | cut -d ' ' -f 1-

删除字符串开头末尾中间的空格和末尾的换行:

echo -n " 12 34 56 " | sed s/[[:space:]]//g | wc -c
#6

只是删除行尾的换行:

echo "sss" | xargs echo -n

将零字符替换为换行:

sudo cat /proc/$pid/environ | tr '\0' '\n'

删除终端输出的颜色控制符:

tail -f my.log | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g"

shell流式处理(cat xxx.txt | sh xxx.sh):

pipeline() {
	while read line;
	do
		echo $line;
		count=$[ $count + 1 ];
	done;
	echo $count
}

count=0

pipeline | sed -r 's/([0-9]{2,2}):([0-9]{2,2}):([0-9]{2,2})\.([0-9]{3,3})[^,]+/\1\2\3\4/g'

----

文件操作:

查看目录下哪些文件不包含某个字符串:

ls ./ | xargs grep -L excludeStr

批量搜索多个文件中的最后一行错误日志:

for f in $(find ./output/*.log); do grep "error" $f | tail -1; done

并加上文件名(注意文件名前后不要加重定向符号<>,小心文件被清空):

for f in $(find ./output/*.log); do echo "== $f =="; grep "error" $f | tail -1; done

将文件内容按行统计出现次数,并按出现次数降序显示:

cat log | sort | uniq -c  | sort -r

将gz日志去掉前导时间戳后(例如只取第51个和之后的字符),对报错内容进行归类:

zcat my.log.gz | cut -c 51- | sort | uniq -c

查看当前目录和一级子目录的大小,不显示当前目录下的文件:

#当前目录
du -h -d 1

#指定其他目录
du -h -d 1 /tmp

给文件名批量加时间后缀:

ls | xargs -I {} mv {} {}\.`date +"%Y%m%d%H%M%S"`

将output文件夹下的日志文件批量移到output-old目录下,并添加时间后缀:

ls ./output/*.log | sed -nr 's/\.\/output\/(.*)/ mv \.\/output\/\1 \.\/output-old\/\1/gp' | xargs -I {} echo {}\.`date +"%Y%m%d%H%M%S"` | sh

删除一个小时前的日志文件:

find ./ -cmin +60 -name "*.log" | xargs rm

批量清空文件:

ls | xargs truncate -s 0

tail -f 指定时间后自动终止:

#10s后终止tail -f
timeout 10 tail -f my.log

修改文件最后更改时间为指定日期:

#2013-09-15 12:00
touch -t 201309151200 -m redis-16379.log

给无法输入的乱码文件名改名:

#查看inode号
ls -i
#通过inode号选择文件并改名
find . -inum $inode | xargs -i mv {} other_name

查看当前目录下每个文件的行数:

wc -l `find . -name '*.txt'`

--end--

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值