shell排错
shell排错
目录
[toc]
案例:shell代码里出现不可见字符<0xa0>
-2024.4.17==(已解决)==
故障现象
目标脚本:(格式有问题版脚本)
mysql5.7.29_install.sh
#!/bin/bash
#MySQL5.7 Download URL: https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.29-linux-glibc2.12-x86_64.tar.gz
. /etc/init.d/functions
SRC_DIR=`pwd`
MYSQL='mysql-5.7.29-linux-glibc2.12-x86_64.tar.gz'
COLOR='echo -e \E[01;31m'
END='\E[0m'
MYSQL_ROOT_PASSWORD=magedu
check (){
if [ $UID -ne 0 ]; then
action "当前用户不是root,安装失败" false
exit 1
fi
cd $SRC_DIR
if [ ! -e $MYSQL ];then
$COLOR"缺少${MYSQL}文件"$END
$COLOR"请将相关软件放在${SRC_DIR}目录下"$END
exit
elif [ -e /usr/local/mysql ];then
action "数据库已存在,安装失败" false
exit
else
return
fi
}
install_mysql(){
$COLOR"开始安装MySQL数据库..."$END
yum -y -q install libaio numactl-libs libaio &> /dev/null
cd $SRC_DIR
tar xf $MYSQL -C /usr/local/
MYSQL_DIR=`echo $MYSQL| sed -nr 's/^(.*[0-9]).*/\1/p'`
ln -s /usr/local/$MYSQL_DIR /usr/local/mysql
chown -R root.root /usr/local/mysql/
id mysql &> /dev/null || { useradd -s /sbin/nologin -r mysql ; action "创建mysql用户"; }
echo 'PATH=/usr/local/mysql/bin/:$PATH' > /etc/profile.d/mysql.sh
. /etc/profile.d/mysql.sh
cat > /etc/my.cnf <<-EOF
[mysqld]
server-id=1
log-bin
datadir=/data/mysql
socket=/data/mysql/mysql.sock
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid
[client]
socket=/data/mysql/mysql.sock
EOF
mkdir -p /data/mysql
chown mysql:mysql /data/mysql
mysqld --initialize --user=mysql --datadir=/data/mysql
cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
chkconfig --add mysqld
chkconfig mysqld on
service mysqld start
[ $? -ne 0 ] && { $COLOR"数据库启动失败,退出!"$END;exit; }
MYSQL_OLDPASSWORD=`awk '/A temporary password/{print $NF}' /data/mysql/mysql.log`
mysqladmin -uroot -p$MYSQL_OLDPASSWORD password $MYSQL_ROOT_PASSWORD &>/dev/null
action "数据库安装完成"
}
check
install_mysql
shell脚本在.sh里执行后报错,但手动复制到linux终端里是可以正常执行的。
shell脚本在.sh里执行后报错:
- ==但手动复制到linux终端里是可以正常执行的:==
测试过程
- 使用cat等命令测试故障文件(无异常)
- 把代码拷贝到sublime里:发现有异常,存在
<0xa0>
异常代码。
解决办法
将shell代码拷贝到sublime里,手动删除,然后再次执行脚本测试。
mysql5.7.29_install.sh
(正确版代码)
#!/bin/bash
#MySQL5.7 Download URL: https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.29-linux-glibc2.12-x86_64.tar.gz
. /etc/init.d/functions
SRC_DIR=`pwd`
MYSQL='mysql-5.7.29-linux-glibc2.12-x86_64.tar.gz'
COLOR='echo -e \E[01;31m'
END='\E[0m'
MYSQL_ROOT_PASSWORD=magedu
check (){
if [ $UID -ne 0 ]; then
action "当前用户不是root,安装失败" false
exit 1
fi
cd $SRC_DIR
if [ ! -e $MYSQL ];then
$COLOR"缺少${MYSQL}文件"$END
$COLOR"请将相关软件放在${SRC_DIR}目录下"$END
exit
elif [ -e /usr/local/mysql ];then
action "数据库已存在,安装失败" false
exit
else
return
fi
}
install_mysql(){
$COLOR"开始安装MySQL数据库..."$END
yum -y -q install libaio numactl-libs libaio &> /dev/null
cd $SRC_DIR
tar xf $MYSQL -C /usr/local/
MYSQL_DIR=`echo $MYSQL| sed -nr 's/^(.*[0-9]).*/\1/p'`
ln -s /usr/local/$MYSQL_DIR /usr/local/mysql
chown -R root.root /usr/local/mysql/
id mysql &> /dev/null || { useradd -s /sbin/nologin -r mysql ; action "创建mysql用户"; }
echo 'PATH=/usr/local/mysql/bin/:$PATH' > /etc/profile.d/mysql.sh
. /etc/profile.d/mysql.sh
cat > /etc/my.cnf <<-EOF
[mysqld]
server-id=1
log-bin
datadir=/data/mysql
socket=/data/mysql/mysql.sock
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid
[client]
socket=/data/mysql/mysql.sock
EOF
mkdir -p /data/mysql
chown mysql:mysql /data/mysql
mysqld --initialize --user=mysql --datadir=/data/mysql
cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
chkconfig --add mysqld
chkconfig mysqld on
service mysqld start
[ $? -ne 0 ] && { $COLOR"数据库启动失败,退出!"$END;exit; }
MYSQL_OLDPASSWORD=`awk '/A temporary password/{print $NF}' /data/mysql/mysql.log`
mysqladmin -uroot -p$MYSQL_OLDPASSWORD password $MYSQL_ROOT_PASSWORD &>/dev/null
action "数据库安装完成"
}
check
install_mysql
哇哦,可以了哦:
总结经验
一些shell执行如果报错,可以按如下方式检查:
1、cat -v file查看文件是否存在异常字符 (如果存在,使用:set ff=uninx
来处理异常字符)
2、将代码拷贝到sublime里,观察是否存在异常字符;
案例:脚本在用户登录时输出大量信息,了干扰非交互式 shell 环境,例如sftp服务-2024.7.28(已解决)
故障环境:
centos7.6 1810虚机
1、故障现象
未在/etc/profile.d目录下放置systyeminfo.sh脚本时,typora里可正常上传图片,ShareX也可正常通过sftp上传图片。
但是一旦该目录下有systyeminfo.sh脚本时,typora里会上传图片失败,ShareX也不能通过sftp上传图片。
这个就很奇怪了呀。。。
未在/etc/profile.d目录下放置systyeminfo.sh脚本时
typora里可正常上传图片:
ShareX也可正常通过sftp上传图片:
/etc/profile.d目录下放置systyeminfo.sh脚本时
typora里会上传图片失败:
ShareX也不能通过sftp上传图片:
这个是为什么呢?
???why
systeninfo脚本内容
[root@docusaurus-wiki ~]#cat /tmp/systeminfo.sh
#!/bin/bash
# by 运维朱工
# site:bash.lutixia.cn
####################################
# 获取IP地址和主机名
IP_ADDR=$(hostname -I | cut -d' ' -f1)
HOSTNAME=$(hostname)
# CPU负载信息:
cpu_load() {
echo -e "\t\t\tcpu的负载情况"
echo -e "\t------------------------------------------------"
echo -e "\tCPU load in 1 min is: `awk '{printf "%15s",$1}' /proc/loadavg`"
echo -e "\tCPU load in 5 min is: `awk '{printf "%15s",$2}' /proc/loadavg`"
echo -e "\tCPU load in 10 min is: `awk '{printf "%15s",$3}' /proc/loadavg`"
echo
}
# mem基本信息:
memory_info() {
echo -e "\t\t\t内存的使用情况"
echo -e "\t------------------------------------------------"
echo -e "\t`free -h | awk '/Mem/{printf "%-10s %s","内存总容量:",$2}'`"
echo -e "\t`free -h | awk '/Mem/{printf "%-10s %s","内存空闲容量:",$4}'`"
echo -e "\t`free -h | awk '/Mem/{printf "%-10s %s","内存缓存:",$6}'`"
echo
}
# 磁盘使用量排序:
disk_rank() {
echo -e "\t\t\t各分区使用率"
echo -e "\t------------------------------------------------"
df -h -x tmpfs -x devtmpfs | sort -nr -k 5 | awk '/dev/{printf "\t%-20s %10s\n", $1, $5}'
echo
}
# 显示系统信息
echo
echo -e "\t\t\t系统基本信息:"
echo -e "\t------------------------------------------------"
echo -e "\tCurrent Time : $(date)"
echo -e "\tVersion : $(cat /etc/os-release | grep -w "PRETTY_NAME" | cut -d= -f2 | tr -d '"')"
echo -e "\tKernel : $(uname -r)"
echo -e "\tUptime : $(uptime -p)"
echo -e "\tIP addr : $IP_ADDR"
echo -e "\tHostname : $HOSTNAME"
echo -e "\tCpu : $(lscpu | grep "Model name:" | sed 's/Model name:\s*//')"
echo -e "\tMemory : $(free -h | awk '/^Mem:/ { print $3 "/" $2 }')"
echo -e "\tSWAP : $(free -h | awk '/^Swap:/ { print $3 "/" $2 }')"
echo -e "\tUsers Logged : $(who | wc -l) users"
echo
cpu_load
memory_info
disk_rank
2、gpt
提问:
systeminfo.sh
#!/bin/bash
# by 运维朱工
# site:bash.lutixia.cn
####################################
# 获取IP地址和主机名
IP_ADDR=$(hostname -I | cut -d' ' -f1)
HOSTNAME=$(hostname)
# CPU负载信息:
cpu_load() {
echo -e "\t\t\tcpu的负载情况"
echo -e "\t------------------------------------------------"
echo -e "\tCPU load in 1 min is: `awk '{printf "%15s",$1}' /proc/loadavg`"
echo -e "\tCPU load in 5 min is: `awk '{printf "%15s",$2}' /proc/loadavg`"
echo -e "\tCPU load in 10 min is: `awk '{printf "%15s",$3}' /proc/loadavg`"
echo
}
# mem基本信息:
memory_info() {
echo -e "\t\t\t内存的使用情况"
echo -e "\t------------------------------------------------"
echo -e "\t`free -h | awk '/Mem/{printf "%-10s %s","内存总容量:",$2}'`"
echo -e "\t`free -h | awk '/Mem/{printf "%-10s %s","内存空闲容量:",$4}'`"
echo -e "\t`free -h | awk '/Mem/{printf "%-10s %s","内存缓存:",$6}'`"
echo
}
# 磁盘使用量排序:
disk_rank() {
echo -e "\t\t\t各分区使用率"
echo -e "\t------------------------------------------------"
df -h -x tmpfs -x devtmpfs | sort -nr -k 5 | awk '/dev/{printf "\t%-20s %10s\n", $1, $5}'
echo
}
# 显示系统信息
echo
echo -e "\t\t\t系统基本信息:"
echo -e "\t------------------------------------------------"
echo -e "\tCurrent Time : $(date)"
echo -e "\tVersion : $(cat /etc/os-release | grep -w "PRETTY_NAME" | cut -d= -f2 | tr -d '"')"
echo -e "\tKernel : $(uname -r)"
echo -e "\tUptime : $(uptime -p)"
echo -e "\tIP addr : $IP_ADDR"
echo -e "\tHostname : $HOSTNAME"
echo -e "\tCpu : $(lscpu | grep "Model name:" | sed 's/Model name:\s*//')"
echo -e "\tMemory : $(free -h | awk '/^Mem:/ { print $3 "/" $2 }')"
echo -e "\tSWAP : $(free -h | awk '/^Swap:/ { print $3 "/" $2 }')"
echo -e "\tUsers Logged : $(who | wc -l) users"
echo
cpu_load
memory_info
disk_rank
这个systeminfo.sh 脚本被放置在/etc/profile.d目录下,用以登录系统后显示机器的一些配置信息。
但是,放置后,我之前利用nginx提供了/images作为一个目录提供图床服务,此时无法正常利用picgo来上传图片了,并且sharex软件也无法通过sftp上传图片了。
将/etc/profile.d目录下的systeminfo.sh移除后,就都正常了。
请帮我看下是什么原因?是这个systeminfo.sh哪里有错吗?
回答:
你的 systeminfo.sh
脚本放置在 /etc/profile.d
目录下后,导致图床服务和文件上传功能无法正常工作。这种情况可能是由于脚本在每次用户登录时执行,并且在某些情况下可能产生了输出或错误,干扰了非交互式 shell 环境的工作。
一些常见的问题包括:
- 输出干扰:脚本在用户登录时输出大量信息,可能干扰非交互式 shell 环境,比如 sftp 和其他服务。
- 潜在错误:脚本可能产生错误输出,这些错误信息可能干扰到其他进程或服务。
可以通过以下方式修改脚本,以减少对非交互式 shell 环境的影响:
1. 确保脚本只在交互式 shell 中运行
在脚本的开头添加条件检查,确保脚本只在交互式 shell 中运行。这可以通过检查 PS1
环境变量是否存在来实现:
#!/bin/bash
# by 运维朱工
# site:bash.lutixia.cn
####################################
# 检查是否为交互式 shell
if [[ $- != *i* ]]; then
return
fi
# 获取IP地址和主机名
IP_ADDR=$(hostname -I | cut -d' ' -f1)
HOSTNAME=$(hostname)
# CPU负载信息:
cpu_load() {
echo -e "\t\t\tcpu的负载情况"
echo -e "\t------------------------------------------------"
echo -e "\tCPU load in 1 min is: `awk '{printf "%15s",$1}' /proc/loadavg`"
echo -e "\tCPU load in 5 min is: `awk '{printf "%15s",$2}' /proc/loadavg`"
echo -e "\tCPU load in 10 min is: `awk '{printf "%15s",$3}' /proc/loadavg`"
echo
}
# mem基本信息:
memory_info() {
echo -e "\t\t\t内存的使用情况"
echo -e "\t------------------------------------------------"
echo -e "\t`free -h | awk '/Mem/{printf "%-10s %s","内存总容量:",$2}'`"
echo -e "\t`free -h | awk '/Mem/{printf "%-10s %s","内存空闲容量:",$4}'`"
echo -e "\t`free -h | awk '/Mem/{printf "%-10s %s","内存缓存:",$6}'`"
echo
}
# 磁盘使用量排序:
disk_rank() {
echo -e "\t\t\t各分区使用率"
echo -e "\t------------------------------------------------"
df -h -x tmpfs -x devtmpfs | sort -nr -k 5 | awk '/dev/{printf "\t%-20s %10s\n", $1, $5}'
echo
}
# 显示系统信息
echo
echo -e "\t\t\t系统基本信息:"
echo -e "\t------------------------------------------------"
echo -e "\tCurrent Time : $(date)"
echo -e "\tVersion : $(cat /etc/os-release | grep -w "PRETTY_NAME" | cut -d= -f2 | tr -d '"')"
echo -e "\tKernel : $(uname -r)"
echo -e "\tUptime : $(uptime -p)"
echo -e "\tIP addr : $IP_ADDR"
echo -e "\tHostname : $HOSTNAME"
echo -e "\tCpu : $(lscpu | grep "Model name:" | sed 's/Model name:\s*//')"
echo -e "\tMemory : $(free -h | awk '/^Mem:/ { print $3 "/" $2 }')"
echo -e "\tSWAP : $(free -h | awk '/^Swap:/ { print $3 "/" $2 }')"
echo -e "\tUsers Logged : $(who | wc -l) users"
echo
cpu_load
memory_info
disk_rank
2. 确保脚本无错误输出
检查脚本中的每个命令,确保没有错误输出。可以通过重定向错误输出到 /dev/null
来防止错误信息干扰其他进程:
# 获取IP地址和主机名
IP_ADDR=$(hostname -I 2>/dev/null | cut -d' ' -f1)
HOSTNAME=$(hostname 2>/dev/null)
通过上述修改,确保 systeminfo.sh
只在交互式 shell 中运行,避免干扰 nginx
或 sftp
服务。这应该能够解决你的问题。如果问题依然存在,建议进一步检查 nginx
和 sftp
服务的日志,以确定具体的错误原因。
3、解决办法
更新代码
cd /etc/profile.d/
vim systeminfo-v2.sh
chmod +x systeminfo-v2.sh
systeminfo-v2-2024.7.28.sh
#!/bin/bash
# by 运维朱工
# site:bash.lutixia.cn
####################################
# 检查是否为交互式 shell
if [[ $- != *i* ]]; then
return
fi
# 获取IP地址和主机名
IP_ADDR=$(hostname -I | cut -d' ' -f1)
HOSTNAME=$(hostname)
# CPU负载信息:
cpu_load() {
echo -e "\t\t\tcpu的负载情况"
echo -e "\t------------------------------------------------"
echo -e "\tCPU load in 1 min is: `awk '{printf "%15s",$1}' /proc/loadavg`"
echo -e "\tCPU load in 5 min is: `awk '{printf "%15s",$2}' /proc/loadavg`"
echo -e "\tCPU load in 10 min is: `awk '{printf "%15s",$3}' /proc/loadavg`"
echo
}
# mem基本信息:
memory_info() {
echo -e "\t\t\t内存的使用情况"
echo -e "\t------------------------------------------------"
echo -e "\t`free -h | awk '/Mem/{printf "%-10s %s","内存总容量:",$2}'`"
echo -e "\t`free -h | awk '/Mem/{printf "%-10s %s","内存空闲容量:",$4}'`"
echo -e "\t`free -h | awk '/Mem/{printf "%-10s %s","内存缓存:",$6}'`"
echo
}
# 磁盘使用量排序:
disk_rank() {
echo -e "\t\t\t各分区使用率"
echo -e "\t------------------------------------------------"
df -h -x tmpfs -x devtmpfs | sort -nr -k 5 | awk '/dev/{printf "\t%-20s %10s\n", $1, $5}'
echo
}
# 显示系统信息
echo
echo -e "\t\t\t系统基本信息:"
echo -e "\t------------------------------------------------"
echo -e "\tCurrent Time : $(date)"
echo -e "\tVersion : $(cat /etc/os-release | grep -w "PRETTY_NAME" | cut -d= -f2 | tr -d '"')"
echo -e "\tKernel : $(uname -r)"
echo -e "\tUptime : $(uptime -p)"
echo -e "\tIP addr : $IP_ADDR"
echo -e "\tHostname : $HOSTNAME"
echo -e "\tCpu : $(lscpu | grep "Model name:" | sed 's/Model name:\s*//')"
echo -e "\tMemory : $(free -h | awk '/^Mem:/ { print $3 "/" $2 }')"
echo -e "\tSWAP : $(free -h | awk '/^Swap:/ { print $3 "/" $2 }')"
echo -e "\tUsers Logged : $(who | wc -l) users"
echo
cpu_load
memory_info
disk_rank
4、测试效果
这次是可以正常上传图片的:
登录系统也是可以正常输出信息的: