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[@]}",要传数组所有元素;函数传数组要用 "$@" 重新接收所有元素,然后再处理数组。

相关推荐
草莓熊Lotso2 小时前
Linux 进程等待与程序替换全解析:从僵尸进程防治到 exec 函数实战
linux·运维·服务器·开发语言·c++·人工智能·python
德彪稳坐倒骑驴2 小时前
PySpark on Linux系统配置 Hadoop3.1.3+Spark3.4.4(PySpark3)
linux·运维·服务器
_F_y2 小时前
MySQL表的内连和外连
android·数据库·mysql
柏木乃一3 小时前
库的制作与原理(2)ELF格式,程序地址空间part2,程序加载
linux·服务器·c++·进程·elf··进程地址空间
杜子不疼.3 小时前
【Linux】基础IO(三):文件描述符与重定向
linux·c语言·开发语言·人工智能
猫猫的小茶馆5 小时前
【Linux 驱动开发】七. 中断下半部
linux·arm开发·驱动开发·stm32·嵌入式硬件·mcu
cyber_两只龙宝5 小时前
LVS-DR模式实验配置及原理详解
linux·网络·云原生·智能路由器·lvs·dr模式
好好学习啊天天向上10 小时前
C盘容量不够,python , pip,安装包的位置
linux·python·pip
a努力。10 小时前
国家电网Java面试被问:混沌工程在分布式系统中的应用
java·开发语言·数据库·git·mysql·面试·职场和发展