Shell脚本中连接数据库查询数据报错 “No such file or directory“以及函数传参数组

Shell脚本中连接数据库查询数据报错 "No such file or directory"以及函数传参数组


前言

业务要求,编写一个Shell脚本,目的是定时从 MySQL 数据库中拉取业务数据,填入 CSV 报表中,并每日凌晨定时推送到远程平台。

在脚本调试过程中遇到了几个问题(Bash语法坑),好久不写Shell了生疏了......

问题1: 执行mysql命令,报错"No such file or directory"

报错

脚本中定义了一个数组用来存放 MySQL 的连接命令和参数,但在执行时报错:

sh 复制代码
# 第一种
MYSQL_CONN='/path/to/mysql -uuser -ppassword -S /tmp/mysql.sock dbname'
# ... 省略中间逻辑 ...
"${MYSQL_CONN}" -e "${sql}"

# 第二种
MYSQL_CONN=(/path/to/mysql -uuser -ppassword -S /tmp/mysql.sock dbname)
# ... 省略中间逻辑 ...
"${MYSQL_CONN[*]}" -e "${sql}"

原因分析

第一种因为我的password里特殊字符如@$符号,如mysql -uuser -p"passw@rd",shell 分词混乱会把密码分割开导致命令执行失败;

从网上查询的第二种方法,我明明 ls 看了,/path/to/mysql 这个文件是绝对存在的,为什么 Shell 还是说找不到文件?

问题的根源在于 ${MYSQL_CONN[*]} 中的这个 *
在 Bash 中,"${arr[*]}" 会把数组中的所有元素合并成一个单一的字符串,中间默认用空格连接。Shell 在执行时,会试图去文件系统中寻找一个文件名叫 "mysql -uuser -ppassword..." 的文件。这当然找不到!文件名里怎么可能有 -u 这种参数呢?

解决方案

将 * 改为 @。"${arr[@]}" 会将数组元素展开为独立的参数,保留参数之间的分隔。这样 Shell 就会正确理解:第一个元素是命令,后面的元素是参数。

sh 复制代码
"${MYSQL_CONN[@]}" -e "${sql}"

问题2: mysql的静默输出

问题

发MySQL 默认返回的结果带漂亮的表格边框,首先想到使用grep、awk等工具去处理

sh 复制代码
+------------------+
| count(username)  |
+------------------+
|                2 |
+------------------+

解决方案

不需要用 grep 或 awk 去切分字符串,直接利用 MySQL 自带的参数:

-N:不显示列头(Header)。

-s:静默模式(Silent),去掉边框线条。

问题3 函数的参数是数组,调用问题

问题

sh 复制代码
fun_c(){
    local para=$1
}
arr=(a,b)
fun_c $arr

在调用函数的时候,发现只有a的处理逻辑,b一直未处理。

原因分析

调用时:$arr 默认只取数组的第一个元素。

接收时:local para=$1 只读取了第一个参数。

解决方案

必须显式地展开数组,并在函数内部用 $@ 重新接收。

sh 复制代码
fun_c(){
# 将传入的所有参数重新组装成数组
    local para=("$@")
    for i in ${para[@]}
}

arr=(a,b)
# 调用时:使用 [@] 并加引号
fun_c "${arr[@]}"

总结

原来一直以为${arr[@]}${arr[*]}是一样的含义,这次发现完全不同,数组展开永远优先使用 "${arr[@]}"。

此外,函数传参传数组要 "${arr[@]}",要传数组所有元素;函数传数组要用 "$@" 重新接收所有元素,然后再处理数组。

相关推荐
天才奇男子1 天前
HAProxy高级功能全解析
linux·运维·服务器·微服务·云原生
学嵌入式的小杨同学1 天前
【Linux 封神之路】信号编程全解析:从信号基础到 MP3 播放器实战(含核心 API 与避坑指南)
java·linux·c语言·开发语言·vscode·vim·ux
酥暮沐1 天前
iscsi部署网络存储
linux·网络·存储·iscsi
❀͜͡傀儡师1 天前
centos 7部署dns服务器
linux·服务器·centos·dns
Dying.Light1 天前
Linux部署问题
linux·运维·服务器
S19011 天前
Linux的常用指令
linux·运维·服务器
小义_1 天前
【RH134知识点问答题】第7章 管理基本存储
linux·运维·服务器
梁洪飞1 天前
内核的schedule和SMP多核处理器启动协议
linux·arm开发·嵌入式硬件·arm
_运维那些事儿1 天前
VM环境的CI/CD
linux·运维·网络·阿里云·ci/cd·docker·云计算
·云扬·1 天前
MySQL Binlog落盘机制深度解析:性能与安全性的平衡艺术
android·mysql·adb