Mysql

MySQL - 為什麼我的 BASH 腳本插入/更新查詢不能正常工作?

  • February 12, 2018

**背景:**我有一個 MySQL 表,用於儲存大量主機的 IP 地址。這是一個簡單的表(主機 xyz -> ip1、ip2、ip3)。這些主機會將帶有其 ip 地址的平面文件寫入中央伺服器(保存 MySQL 數據庫的地方),一個簡單的 BASH shell 腳本將處理該文件並將資訊插入/更新到 MySQL 數據庫的 ip 表中。

**我的舊ip呢?**一切正常,除了我注意到如果主機未能將其 IP 地址之一寫入平面文件,BASH shell 腳本中的插入/更新查詢將刪除舊的 IP 地址。我想保留那個IP地址。

**我應該使用 COALESCE 對嗎?**好吧,我用 COALESCE 重建了我的查詢,它可以在 phpMyAdmin 和 mysql 終端中執行。

**問題:**我將閃亮的新查詢放入 BASH shell 腳本中,但它仍然會刪除我的舊 ips(插入/更新之前主機存在的 ips)。

我可以整天將查詢複製並粘貼到 mysql 終端或 phpMyAdmin 中,它的行為完全符合我的要求。當我讓 bash shell 腳本執行此操作時,它會清除查詢中未明確設置的任何內容。

我以非常詳細的方式執行查詢以查看所有內容。我將相同的 IP 地址移動到不同的 eth#s,但是當通過 bash shell 腳本執行查詢時,舊的地址會不斷被刪除。我將相同的查詢複製/粘貼到 phpMyAdmin 或 mysql 終端中,它工作正常——沒有 ips 被刪除。

第一次使用 eth3=ip 執行(通過 mysql):

詢問:

INSERT INTO ip
 (host_id
 ,eth0
 ,eth1
 ,eth2
 ,eth3)
VALUES
 ('HOST1234'
 ,NULL
 ,NULL
 ,NULL
 ,INET_ATON('172.16.5.83'))
ON DUPLICATE KEY UPDATE
 eth0 = COALESCE(NULL,eth0)
 ,eth1 = COALESCE(NULL,eth1)
 ,eth2 = COALESCE(NULL,eth2)
 ,eth3 = COALESCE(INET_ATON('172.16.5.83'),eth3)

結果:

host_id     eth0        eth1        eth2        eth3
==========================================================
HOST1234    NULL        NULL        NULL        2886731091

第二次使用 eth2=ip 執行(通過 mysql):

詢問:

INSERT INTO ip
 (host_id
 ,eth0
 ,eth1
 ,eth2
 ,eth3)
VALUES
 ('HOST1234'
 ,NULL
 ,NULL
 ,INET_ATON('172.16.5.83')
 ,NULL)
ON DUPLICATE KEY UPDATE
 eth0 = COALESCE(NULL,eth0)
 ,eth1 = COALESCE(NULL,eth1)
 ,eth2 = COALESCE(INET_ATON('172.16.5.83'),eth2)
 ,eth3 = COALESCE(NULL,eth3)

結果:

host_id     eth0        eth1        eth2        eth3
==========================================================
HOST1234    NULL        NULL        2886731091  2886731091

使用 eth3=ip 進行第三次執行(通過 bash 腳本):

詢問:

INSERT INTO ip
 (host_id
 ,eth0
 ,eth1
 ,eth2
 ,eth3)
VALUES
 ('HOST1234'
 ,NULL
 ,NULL
 ,NULL
 ,INET_ATON('172.16.5.83'))
ON DUPLICATE KEY UPDATE
 eth0 = COALESCE(NULL,eth0)
 ,eth1 = COALESCE(NULL,eth1)
 ,eth2 = COALESCE(NULL,eth2)
 ,eth3 = COALESCE(INET_ATON('172.16.5.83'),eth3)

結果:

host_id     eth0        eth1        eth2        eth3
==========================================================
HOST1234    NULL        NULL        NULL        2886731091

我希望這是有道理的。我已經花了大約 16 個小時來嘗試不同的方法,但我無法弄清楚這一點。請幫忙。我將提供您可能需要的任何其他合格資訊,以幫助我找到答案。謝謝!

BASH 外殼腳本:

#!/bin/bash
file_path="/IP/"
while true; do
   file_name=`find $file_path -mount -maxdepth 1 -type f -name "*.IP*" -printf "%f\n" | head -1`
   if [ "$file_name" != "" ];then
       echo "$file_name"

       host_id=`cat $file_path$file_name | grep "HOST_ID" | sed 's/^.*=//' | tr '[:lower:]' '[:upper:]' | cut -c1-13`
       eth0=`cat $file_path$file_name | grep "ETH0" | sed 's/^.*=//'`
       if [ "$eth0" != "" ];then
           eth0="INET_ATON('$eth0')"
       else
           eth0=NULL
       fi
       eth1=`cat $file_path$file_name | grep "ETH1" | sed 's/^.*=//'`
       if [ "$eth1" != "" ];then
           eth1="INET_ATON('$eth1')"
       else
           eth1=NULL
       fi
       eth2=`cat $file_path$file_name | grep "ETH2" | sed 's/^.*=//'`
       if [ "$eth2" != "" ];then
           eth2="INET_ATON('$eth2')"
       else
           eth2=NULL
       fi
       eth3=`cat $file_path$file_name | grep "ETH3" | sed 's/^.*=//'`
       if [ "$eth3" != "" ];then
           eth3="INET_ATON('$eth3')"
       else
           eth3=NULL
       fi

mysql -v -v -u root -ppassword ccbu<<EOFMYSQL
INSERT INTO
ip
(host_id
,eth0
,eth1
,eth2
,eth3)
VALUES
('$host_id'
,$eth0
,$eth1
,$eth2
,$eth3)
ON DUPLICATE KEY UPDATE
eth0 = COALESCE($eth0,eth0)
,eth1 = COALESCE($eth1,eth1)
,eth2 = COALESCE($eth2,eth2)
,eth3 = COALESCE($eth3,eth3);
EOFMYSQL
       sudo rm -fv $file_path$file_name
   fi
done

範例 IP 文件:

HOST_ID=HOST1234
ETH3=172.16.5.83

SQL小提琴:

http://sqlfiddle.com/#!9/3e56c/1

**解決方案:**重啟伺服器

我討厭我的生活…

您向我們展示的查詢永遠無法執行您顯示為“第二次執行”的內容。你需要類似的東西

insert into ip (host_id, eth3)
  values ('HOST1234', inet_aton('172.16.5.83'))
ON DUPLICATE KEY UPDATE
 eth0 = COALESCE(eth0,eth1)
,eth1 = COALESCE(eth1,eth2)
,eth2 = COALESCE(eth2,eth3)
,eth3 = COALESCE(eth3,values(eth3))

使用空參數合併沒有任何意義,因為您知道結果。我用一個新值填充 eth3,將舊值移到前面,直到所有四列都被填滿。此後,進一步的插入無效。

以及如何修改 bash 腳本的範例(每個文件只讀一次):

#!/bin/bash
file_path="/tmp/"
typeset -u host_id
while true; do
   for file_name in $file_path/*.IP*
   do
     if [ "$file_name" != "$file_path/*.IP*" ];then
       echo "$file_name"
       eth0=NULL
       eth1=NULL
       eth2=NULL
       eth3=NULL
       while read LINE
       do
         case "$LINE" in
           HOST_ID=*)
             host_id=${LINE/*=}
             ;;
           ETH0=*|ETH1=*|ETH2=*|ETH3=*)
             ethn=${LINE/=*/}
             ethn=${ethn/ETH/}
             typeset eth${ethn}="INET_ATON('${LINE/*=/}')"
             ;;
         esac
       done < $file_name
       echo $host_id $eth0 $eth1 $eth2 $eth3
     else
       echo "Here be no files! :-("
     fi
   done
   sleep 5
done

在“echo”之後添加mysql更新 $ host_id $ eth0 $ eth1 $ eth2 $eth3”。

引用自:https://dba.stackexchange.com/questions/197604