【问题标题】:Execute bash command in batch with mysql results使用mysql结果批量执行bash命令
【发布时间】:2019-09-09 13:44:55
【问题描述】:

我通过 bash 脚本维护了多个具有相同 Web 应用程序的服务器。命令基本包括ssh和scp,每个服务器都是一样的,只是服务器的IP、用户和端口不同。到目前为止,我编写了与服务器一样多的命令以在同一脚本中维护。这很好用,但是当我开始有许多服务器要维护时,我更愿意在 MySQL 表中列出这些服务器,然后在我的 bash 脚本中使用这个列表,因此当我有时我不需要保持所有服务器更新要维护的新服务器。

目前我无法以适当的方式从 MySQL 中提取数据,然后可以在 bash 脚本中执行。

我目前的方法是在查询中使用 CONCAT 函数,如下所示:

outputofquery=$($MYSQL -u"$USER" --batch -p"$PASSWORD" --skip-column-names -h"$HOST" -e "SELECT CONCAT('scp -P ', server_port, ' $file ', server_user, '@', server_ip, ':/var/www/html/site/') FROM server_ssh;" $DBNAME)
echo ${outputofquery%$'\t;'*}

给出以下结果:

scp -P 22 text.php user1@1.1.1.1:/var/www/html/site/ scp -P 12345 text.php user2@2.2.2.2:/var/www/html/site/

MySQL 查询产生的每个命令都放在同一行,这意味着无法执行..

我想在查询中的 site/ 之后添加一个分号,这样即使每个命令都在同一行上,它们也可以独立执行,但碰巧只有最后一个 scp 命令被执行,之前的命令被忽略。

您能否告诉我如何使用来自 MySQL 表的数据批量执行 ssh 和 scp 命令?

【问题讨论】:

    标签: mysql bash


    【解决方案1】:

    最后我成功地使用 MySQL 数据执行批处理命令。根据从 MySQL 中提取的行号,我构建了使用 concatenate 函数执行的命令。下面是我的脚本

    #!/bin/sh
    
    HOST="localhost"
    USER="root"
    DBNAME="mydb"
    PASSWORD="mypassord"
    MYSQL="/Applications/XAMPP/bin/mysql"
    
    file='text.php'
    i=0;
    command='';
    
    ips_and_ports=$($MYSQL -u"$USER" -p"$PASSWORD" -h"$HOST" -BNe "SELECT server_port,server_user,server_ip FROM server_ssh;" $DBNAME)
    for line in $ips_and_ports
    do
        (( i++ )); #increment the line number
    
        if [ $(($i % 3)) -eq 1 ] #check if it is the first element of a line extracted from MySQL (server_port)
        then
            command="scp -P $line"; #initialize a new command to execute
        elif [ $(($i % 3)) -eq 2 ] #check if it is the second element of a line extracted from MySQL (server_user)
        then
            command+=" $file $line@"; #concatenate
        elif [ $(($i % 3)) -eq 0 ] #check if it is the third element of a line extracted from MySQL (server_ip)
        then
            command+="$line:/var/www/html/my_web_app/;"; #concatenate
            eval $command; #execute the command 
        fi
    done;
    

    【讨论】:

      【解决方案2】:

      我是新人,无法发表评论。

      您是否尝试在 mysql 连接的末尾添加 \n 或 && ?

      您还可以更改方法并将服务器和端口分配给变量并循环这些变量以执行ssh 和scp 命令。例如

      ips_and_ports=$($MYSQL -u"$USER" --batch -p"$PASSWORD" --skip-column-names -h"$HOST" -e "SELECT server_port, server_ip FROM extranet.server_ssh;" $DBNAME)
      for $line in $ips_and_ports
      do
          OLDIFS=$IFS;
          IFS="    "; # set the separator to the tab character (PS: this is 4 spaces, change accordingly )
          for $el in $line
          do
              set -- $el; # separate each line by tab and assign the variables to $1, $2 ..
              port=$1;
              ip=$2;
              scp -P 22 text.php user1@$ip:/var/www/html/site/ scp -P $port
          done;
          IFS=$OLDIFS; # put the separator back to it's original value
      done;
      

      我还没有测试过代码,但我希望你明白我的想法!

      祝你好运

      link中有关 IFS 和 OLDIFS 的更多信息

      【讨论】:

      • 非常感谢您的反馈。不幸的是,添加 \n 或 && 不会改变任何东西。您在下面描述的方法很有趣,不幸的是 $line 中的值仅包含一个字段,而不是 SELECT 中的所有字段
      • 我发现这个link 在查询结果中使用了分隔符,。第一个 for 然后在行上正确循环(您也应该将 $IFS 更改为“,”)。我认为的问题是,默认情况下分隔符是各种空格,而不是 \n 单独
      • 谢谢,但不是更好。无论如何,我通过在这个线程中连接要执行的命令(我把我的脚本放在一个单独的答案中)找到了一个解决方案
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-05
      • 1970-01-01
      • 1970-01-01
      • 2021-07-12
      • 2017-12-29
      • 1970-01-01
      • 2013-10-26
      相关资源
      最近更新 更多