我正在修改一组处理视频文件的bash脚本,并将处理步骤报告给mysql数据库(这里是问题original code)。
执行数据库报告的函数是从主处理脚本调用的,在原始文件中看起来像这样:
_report_to_db(){
if [ "${REPORT_TO_DB}" = "Y" ] ; then
echo "INSERT IGNORE INTO tableA (objectIdentifierValue,object_LastTouched) VALUES ('${MEDIA_ID}',NOW()) ON DUPLICATE KEY UPDATE object_LastTouched = NOW()" | mysql --login-path="${LOGIN_PROFILE}" "${DB_NAME}" 2> /dev/null
_db_error_check
fi
}
由于脚本是直接从命令行运行的,所以当你以这种方式运行它时它可以正常工作。但我正在通过网络界面上的php运行它们,并且有一些恶作剧正在进行空格和/或变量的引用/转义。
例如,脚本在...| mysql
之后的空白处打破,它认为我试图以root身份运行mysql而没有密码,完全忽略了--login-path
以及我正在管道的其他东西它。
当我从这样的变量中调用mysql
时:
_report_to_db(){
if [ "${REPORT_TO_DB}" = "Y" ] ; then
SQL_ARRAY=(INSERT IGNORE INTO tableA (columnA,lastTouched) VALUES ("${SOME_PASSED_VALUE}",NOW()) ON DUPLICATE KEY UPDATE object_LastTouched = NOW();)
MYSQL_COMMAND_ARRAY=(mysql --login-path="${LOGIN_PROFILE}" -e "${SQL_ARRAY[@]}" "${DB_NAME}")
echo "$(${MYSQL_COMMAND_ARRAY[@]})"
_db_error_check
fi
}
...我能够正确登录mysql,但忽略了SQL查询(当echo
得到标准MySQL --help
输出结果时。
到目前为止,我已尝试过引用,转义,引用查询作为单独的字符串变量的各种变体,作为数组(如此处所示)。
原来的_db_error_check()
函数只检查管道退出状态的值,这也没有帮助。因此,如果管道正常,但路径下方存在问题,则会无声地失败。
_db_error_check(){
if [ "$?" != "0" ] ; then
# reports an error if the pipe exit value ≠ 0
else
# everything is ok! even if there was a mysql error
fi
}
这不是文件或数据库权限问题(已经三重检查)。我有没有引用或其他一些愚蠢的事情?谢谢!哦,我正在运行OSX El Capitan。
更新
大声笑,我打算发布调用该脚本的PHP,然后我记得PHP实际上调用了一个Pyhton脚本,它也做了一些其他的处理,那个就是调用bash的脚本。这一切都是:
PHP
$command = escapeshellcmd("/usr/local/bin/python3 /Users/user/path/to/ingest.py " . $user . " 2>&1");
while (@ ob_end_flush());
$proc = popen($command, 'r');
echo '<pre>';
while (!feof($proc))
{
echo fread($proc, 4096);
@ flush();
}
echo '</pre>';
PYTHON
for item in os.listdir(ingestDir):
if not item.startswith("."):
filePath = os.path.abspath(ingestDir+"/"+item)
fileNameForMediaID = os.path.splitext(item)[0]
try:
ingest = subprocess.Popen(['/usr/local/bin/ingestfile','-e','-u',user,'-I',filePath,'-m',fileNameForMediaID])
ingest.wait()
os.remove(filePath)
except IOError as err:
print("OS error: {0}".format(err))
更新2
我认为这可能实际上是我安装的奇怪怪癖(如图)。在我的主机上的shell中使用mysql --login-path=myDbUser [etc...]
我不断收到客户端用户为ERROR 1045 (28000): Access denied for user 'ADMIN'@'localhost' (using password: NO)
的错误ADMIN
,并且我尝试以myDbUser
登录。
我实际上uninstalled and reinstalled mysql(通过Homebrew)仍然有相同的结果。使用不同的机器(运行Sierra,但是相同的mysql版本)我可以成功运行上面的shell命令并以目标用户身份登录到mysql。
同样在主机上,我可以sudo -u _www zsh
并以Apache用户(运行整个节目的用户)运行命令而没有问题。所以为什么它不能正确地运行在作为我的主要客户用户的脚本中或者从其中运行???
有什么想法吗? $PATH
在上述所有情况下都是相同的。相同的~/.mylogin.cnf
设置。我错过了还有什么明显的愚蠢吗?
答案 0 :(得分:1)
您需要在此处使用间接扩展:
echo "$(${MYSQL_COMMAND_ARRAY[@]})"
PS:如果我可以提出一个我的个人意见,有一个PHP链 - &gt; python - &gt; bash是你能遇到的最糟糕的编码风格,你可能想把它改写成单一的语言,这样至少可以更容易地找到进一步的问题。如果参数的第一个字符是感叹号(!),和 参数不是nameref,它引入了一个变量级别 间接。 Bash使用从其余部分形成的变量的值 参数作为变量的名称;那么这个变量就是 扩展,该值用于替换的其余部分, 而不是参数本身的价值。这被称为间接的 扩张。如果参数是nameref,则会扩展为名称 参数引用而不是执行完整的变量 间接扩张。对此的例外是扩展 $ {!prefix *}和$ {!name [@]}如下所述。感叹号 必须立即按照左括号进行介绍 间接。
${!name[@]} ${!name[*]}
如果name是数组变量,则展开到数组索引列表 (键)名称分配。如果name不是数组,则在name时扩展为0 设置为null,否则为null。使用“@”时会出现扩展 在双引号内,每个键扩展为一个单独的单词。