Linux Shell常用小技巧

1.批量替换文件中匹配字符串

# sed不支持零宽断言,所以匹配@和<<之间的内容,不包括<<,可以用`@[^< ]*`
# 这个正则代表@和空格或者<之间,且不包含空格和<
sed -i 's/@[^<]*<<//g' /path/to/directory/*.sh

-i 表示在原始文件中直接修改,而不是输出到标准输出

s/ 表示替换操作的开始

@[^<]*<< 正则表达式,以@开头,零个或者多个非<字符,<<结尾

// 表示替换成空字符,也表示删除

g 表示全局替换,即文件中的每一处匹配字符串都会被替换

2.打印输出的某一列

df -k|awk '{print $5}'

打印第五列

3.grep不输出匹配结果

#!/bin/bash
# 如果不用-q,会把匹配行也打印出来
if cat test.sh|grep -q sqlplus;then
  echo 'ok'
else
  echo 'ng'
fi
#!/bin/bash
# name:IOErrorDisablePath.sh
# author:monkey
# date:20230602
# describe:When the path encounters an error, disable this path.

# The path to the monitored log file.
LOG_FILE="/var/adm/vx/dmpevents.log"

# The keyword being monitored.
KEYWORD="I/O error"

tail -F "$LOG_FILE" | while read -r line; do
	if echo "$line" | grep -q "$KEYWORD"; then
		ErrorPath=$(echo "$line" | grep -oP '(?<=Path )\w+(?=\()')
		sleep 2
		if vxdmpadm getsubpaths | grep -i "$ErrorPath" | grep -q "DISABLED"; then
			echo "Path $ErrorPath is already disabled."
		else
			echo "Disabling path: $ErrorPath"
			pwwn=$(vxdmpadm getportids path=$ErrorPath | tail -1 | awk '{print $4}')
			vxdmpadm disable pwwn=$pwwn
		fi
	fi
done

4.root以oracle身份执行命令

主要有两种方式,一种是su -c,一种是su -l,其中su -l会进去到oracle用户的shell环境中(包括环境变量),常用于脚本中。su -c不会进去oracle用户的shell环境中,不过能包含环境白能量,常用于以oracle用户执行单个命令

4.1.su -c方式

# 在root下查看oracle数据库监听状态
su - oracle -c "lsnrctl status"

4.2.su -l方式

su -l oracle << eof
sqlplus -S / as sysdba << eofsp
show pdbs;
eofsp
eof

5.scp无需存储know_host

修改sshd的配置文件

vi /etc/ssh/ssh_config
#################################
#rictHostKeyChecking no
#UserKnownHostsFile /dev/null
#################################

6.保证同一时间只有一个shell脚本实例在运行

使用一个文件来表示是否有脚本实例在运行,如果文件存在,就说明有实例在运行
判断部分主要是防止进程执行完了但是文件未被清理(例如被kill -9),kill -0可以看看进程号对应的进程是否还在,后面的ps -fp可以保证进程号跑的进程就是这个脚本的实例

#!/bin/bash
# name: single_instance_script.sh
# author: monkey
# date: 20231114
# describe: Ensure that only one instance of this script is running at a time

SCRIPT_PATH=$(readlink -f "$0")
SCRIPT_NAME=$(basename "$SCRIPT_PATH")
LOCKFILE="$(dirname $SCRIPT_PATH)/.${SCRIPT_NAME}.lock"

# Check if lock file exists and another instance is running
if [ -e "$LOCKFILE" ] && kill -0 "$(cat "$LOCKFILE")" && ps -fp $(cat "$LOCKFILE") | grep -q "$SCRIPT_NAME"; then 
    echo "Another instance is already running. Exiting.--->$(date +"%Y-%m-%d %H:%M:%S")"
    exit 1
fi

# Make sure the lockfile is removed when we exit and then claim it 
trap "rm -f $LOCKFILE; exit" INT TERM EXIT
echo $$ > "$LOCKFILE"

# Place the main logic part of the script here
echo "Script is running..."
sleep 100
echo "Script completed."

7.获取shell脚本路径

#!/bin/bash
dir=$(dirname "$0")
echo "$dir"

dir=$(pwd)
echo "$dir"

dir=$(dirname $(realpath "$0"))
echo "$dir"

dir=$(dirname "${BASH_SOURCE[0]}")
echo "$dir"

dir=$(dirname "$(readlink -f "$0")")
echo "$dir"

在root用户的crontab下的输出:

脚本在/data/scripts/下,在/data下执行sh scripts/get_current_path.sh命令,输出结果:

posted @ 2023-06-02 11:59  monkey6  阅读(23)  评论(0编辑  收藏  举报