简体   繁体   English

bash脚本不使用作为变量传递的值执行mysql命令

[英]bash script not executing mysql command with values passed as variables

I am modifying a set of bash scripts that process video files and reports the processing steps to a mysql database (here is the original code in question).我正在修改一组处理视频文件并将处理步骤报告给 mysql 数据库的 bash 脚本(这是有问题的原始代码)。

The function that does the database reporting is called from the main processing script and looks like this in the original:执行数据库报告的函数是从主处理脚本中调用的,在原始脚本中如下所示:

_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
}

Since the scripts are meant to be run directly from the command line, when you run them that way it works fine.由于脚本旨在直接从命令行运行,因此当您以这种方式运行它们时,它可以正常工作。 But I'm running them via php from a web interface and there's some shenanigans going on with the quoting/escaping of whitespace and/or variables.但是我正在通过 php 从 Web 界面运行它们,并且在引用/转义空格和/或变量时有一些恶作剧。

For instance, the script breaks on the whitespace after ...| mysql例如,脚本在...| mysql之后的空格处中断...| mysql ...| mysql and it thinks I'm trying to run mysql as root without a password and totally ignores the --login-path and the other stuff I'm piping to it. ...| mysql并且它认为我试图在没有密码的情况下以 root 身份运行 mysql 并完全忽略--login-path和我正在向它传递的其他内容。

When I call mysql from a variable like so:当我从这样的变量调用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
}

... I am able to log into mysql correctly but the SQL query is ignored (when it echo s the result you get the standard MySQL --help output. ...我能够正确登录到 mysql,但 SQL 查询被忽略(当它echo是结果时,您将获得标准的 MySQL --help输出。

So far I have tried all kinds of variations on quoting, escaping, referencing the query as a separate string variable, as an array (as you see here).到目前为止,我已经尝试了各种引用、转义、将查询作为单独的字符串变量引用、作为数组(如您所见)的各种变体。

What is also not helpful is that the original _db_error_check() function only checks the value of the pipe exit status.同样没有帮助的是原始_db_error_check()函数只检查管道退出状态的值。 So if the pipe is ok, but there's a problem further down the path, it fails silently.因此,如果管道没问题,但在路径更远的地方出现问题,它会默默地失败。

_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
}

This is not a file or database permissions issue (already triple checked that).这不是文件或数据库权限问题(已经三重检查了)。 Are there quotes or some other stupid thing that I am missing??有没有我遗漏的引号或其他一些愚蠢的东西? Thanks!谢谢! Oh, I am running OSX El Capitan.哦,我正在运行 OSX El Capitan。

UPDATE更新

Lol, I was going to post the PHP that calls the script and then I remembered that the PHP is actually calling a Pyhton script that does some other processing too, and that is what calls the bash script.大声笑,我打算发布调用脚本的 PHP,然后我想起 PHP 实际上正在调用一个 Pyhton 脚本,它也执行一些其他处理,就是调用 bash 脚本的原因。 Here it all is:一切都在这里:

PHP 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 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))

UPDATE 2更新 2

I think this might actually be a weird quirk of my installation (go figure).我认为这实际上可能我安装的一个奇怪的怪癖(去图)。 Using mysql --login-path=myDbUser [etc...] from a shell on my host machine I keep getting the error ERROR 1045 (28000): Access denied for user 'ADMIN'@'localhost' (using password: NO) where the client user is ADMIN and I am trying to login as myDbUser .在主机上的 shell 中使用mysql --login-path=myDbUser [etc...]我不断收到错误ERROR 1045 (28000): Access denied for user 'ADMIN'@'localhost' (using password: NO)客户端用户是ADMIN并且我尝试以myDbUser身份登录。

I actually uninstalled and reinstalled mysql (via Homebrew) and still have the same results.我实际上卸载并重新安装了 mysql (通过 Homebrew)并且仍然有相同的结果。 Using a different machine (running Sierra, but the same mysql version) I can run the above shell command successfully and log into mysql as the target user.使用不同的机器(运行 Sierra,但相同的 mysql 版本)我可以成功运行上述 shell 命令并以目标用户身份登录 mysql。

Also on the host machine, I can sudo -u _www zsh and run the command as the Apache user (which is the user running the whole show) without a problem.同样在主机上,我可以sudo -u _www zsh并以 Apache 用户(即运行整个节目的用户)身份运行命令,没有问题。 SO WHY IS IT NOT RUNNING CORRECTLY EITHER IN THE SCRIPT OR EVEN RUN FROM SHELL AS MY MAIN CLIENT USER???那么为什么它既不能在脚本中正确运行,也不能以我的主要客户端用户身份从 Shell 中正确运行???

Any ideas?有任何想法吗? $PATH is identical in all cases mentioned above. $PATH在上述所有情况下都是相同的。 Same ~/.mylogin.cnf setups.相同的~/.mylogin.cnf设置。 Is there anything else stupid obvious I missed?还有什么愚蠢的明显我错过了吗?

You need to use indirect expansion here:您需要在此处使用间接扩展:

  echo "$(${MYSQL_COMMAND_ARRAY[@]})"

the man says: 男人说:

If the first character of parameter is an exclamation point (!), and parameter is not a nameref, it introduces a level of variable indirection.如果参数的第一个字符是感叹号 (!),并且参数不是 nameref,则它引入了一个变量间接级别。 Bash uses the value of the variable formed from the rest of parameter as the name of the variable; Bash 使用由参数的其余部分形成的变量的值作为变量的名称; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of parameter itself.这个变量然后被扩展,并且该值用于替换的其余部分,而不是参数本身的值。 This is known as indirect expansion.这称为间接扩展。 If parameter is a nameref, this expands to the name of the variable referenced by parameter instead of performing the complete indirect expansion.如果 parameter 是 nameref,这将扩展为 parameter 引用的变量的名称,而不是执行完整的间接扩展。 The exceptions to this are the expansions of ${!prefix*} and ${!name[@]} described below.例外情况是下面描述的 ${!prefix*} 和 ${!name[@]} 的扩展。 The exclamation point must immediately follow the left brace in order to introduce indirection.感叹号必须紧跟在左大括号之后才能引入间接性。

 ${!name[@]} ${!name[*]}

If name is an array variable, expands to the list of array indices (keys) assigned in name.如果 name 是一个数组变量,则扩展到 name 中分配的数组索引(键)列表。 If name is not an array, expands to 0 if name is set and null otherwise.如果 name 不是数组,则在设置 name 时扩展为 0,否则为 null。 When '@' is used and the expansion appears within double quotes, each key expands to a separate word.当使用 '@' 并且扩展出现在双引号内时,每个键都扩展为一个单独的词。

PS: If I may put forward a piece of my personal opinion, having a chain of php -> python -> bash is the worst coding style one can ever met, you may want to rewrite it into single langue so it will be easier to track down further issues at least. PS:如果我可以提出一个我个人的意见,有一个 php -> python -> bash 链是你见过的最糟糕的编码风格,你可能想把它改写成单语,这样会更容易至少追踪进一步的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM