【问题标题】:bash scripting variable allocation when using here-document使用here-document时的bash脚本变量分配
【发布时间】:2012-12-15 14:32:19
【问题描述】:

我是 bash /mysql 的新手,但是我在阅读抛出的示例和其他人的问题时发现了很多帮助……但遇到了我自己的问题。 每次将文件添加到特定目录时,我都会尝试在 MySQL 数据库表中插入一行(为此我使用的是 inotifywait )无论如何这是我的 bash 脚本

#!/bin/bash

while true; do
        filename= "false"
        filename= inotifywait --format "%f" -e create /var/www/media2net/torrent
        date_field= date +"%F":"%T"
        mysql --host=localhost --user=root --password=admin Media2net << EOF
        insert into video (title, description, url_video, upload_date)
                values('testing','default_description','$filename', '$date_feild');
        EOF
        echo $filename
done

据此,我已经通过 echo 验证了变量 $filename 正确保存在 bash 脚本的末尾,但是当我查看表中的条目时,url_video 列具有它的默认值,而不是 $filename 表示的字符串

据我所知,变量$filename 没有通过 EOF 我已经尝试过这里指出http://www.dba-oracle.com/t_access_mysql_with_bash_shell_script.htm

还有这个

Using shell script to insert data into remote MYSQL database

如果我能找到如何将变量传递给查询的任何帮助,将不胜感激

【问题讨论】:

  • = 周围不能有空格。这个命令filename= "false"临时将环境变量“filename”设置为空字符串,然后执行名为“false”的程序。

标签: mysql linux bash eof


【解决方案1】:

在您的示例中,filename 设置为空字符串(注意= 符号后面的空格!)。你需要

filename=$(inotifywait --format "%f" -e create /var/www/media2net/torrent)

同样,

date_field=$(date +"%F:%T")

请注意,您的 mysql 命令中有错字(date_field 并注意 date_feild):

mysql --host=localhost --user=root --password=admin Media2net <<EOF
insert into video (title, description, url_video, upload_date)
values('testing','default_description','$filename', '$date_field');
EOF

现在我希望你正在控制文件名。想象一个包含单引号的文件名,例如hello'howdy。您的查询会出现问题。更糟糕的是,一个邪恶的用户放置了一个名为whatever','something'); evil_mysql_command; whatever 的文件,你将执行邪恶的命令!一种可能性是使用printf 清理文件名,因此:

printf -v filename '%q' "$(inotifywait --format "%f" -e create /var/www/media2net/torrent)"

这至少会转义可能出现在文件名中的单引号。请参阅 Gordon Davisson 的评论:printf 技巧不会阻止所有可能的攻击,所以我真的希望你绝对控制文件的名称!

所有这些建议都会产生以下脚本:

#!/bin/bash

while true; do
    printf -v filename '%q' "$(inotifywait --format "%f" -e create /var/www/media2net/torrent)"
    date_field=$(date +"%F:%T")
    mysql --host=localhost --user=root --password=admin Media2net <<EOF
    insert into video (title, description, url_video, upload_date) 
    values('testing','default_description','$filename', '$date_field');
    EOF
    echo "$filename"
done

编辑。

在评论中回答你的问题:

为什么脚本正确地将$filename 回显到我的终端但没有正确发送到MySQL,这与以空格开头的字符串有关吗?还是别的什么?

那是因为当您执行以下操作时:

whatever= command

然后将变量whatever设置为空字符串,并执行命令command(将whatever变量设置为环境变量)。例如,

$ IFS='c' read a b c <<< "AcBcC"
$ echo "$a $b $c"
A B C
$ echo $IFS

$

在您的脚本中,变量文件名实际上从未全局设置。您可以通过以下方式进行检查:

$ filename= "false"
$ echo "$filename"

$

发生的情况是环境变量filename 设置为空字符串,然后使用该环境变量启动命令false(恰好存在),我们就完成了。

当你这样做时:

filename= inotifywait --format "%f" -e create /var/www/media2net/torrent

变量filename设置为空字符串,然后以filename作为环境变量执行命令inotifywait ...(但inotifywait并不关心它)。 这就是你在终端上看到的!这是这个命令的输出。然后你可能看到了一个空行,那是

的输出
echo $filename

相当于

echo

因为变量filename 扩展为一个空字符串。

希望这会有所帮助。

【讨论】:

  • 啊啊啊,非常感谢!你对文件名的建议奏效了!!!为了满足我自己的好奇心,为什么脚本正确地将 $filename 回显到我的终端但没有正确地将其发送到 MySQL ,这与以空格开头的字符串有关吗?还是别的什么?
  • 我还没有走那么远,还没有!虽然我知道某些性质的问题是一个问题,但您知道网络上的任何参考资料详细说明了这种性质的更多问题吗?
  • 关于通过文件名进行 SQL 注入的好点,但请注意,如果这种类型的攻击是一个可能的问题,printf ... '%q' 是不够的。它执行 bash 风格的字符串引用/转义,而 mysql 有一些不同的引用规则,攻击者可以利用这种差异。正确防御 SQL 注入是困难
  • 还有这个 printf -v 行,在 ubuntu 12.04 中返回一个非法选项,尽管文档建议语法是正确的?无论如何,我会阅读有关防止 SQL 注入的内容,因为 Gordon 已经明确表示涉及多个步骤
  • @brendanmorrison 确保您运行的是bash 而不是sh-v 选项仅适用于 printf bash 内置。
猜你喜欢
  • 2020-09-30
  • 2012-10-26
  • 2015-01-31
  • 1970-01-01
  • 2020-08-14
  • 1970-01-01
  • 2021-11-04
  • 2012-06-18
  • 2016-12-08
相关资源
最近更新 更多