テーブルを更新するために、小さなデータベースに対してsqlite3クエリを実行しようとしています。スクリプトはより複雑ですが、テスト用に次の変数を設定しました。
DN=123
UP=123
downlocalip=10.1.2.3
downremoteip=123
uplocalip=123
upremoteip=123
次に、次のコマンドを実行してテーブルを更新します。
sqlite3 /var/www/server/newserverstats.db "UPDATE stats SET downspeed='''$DN''', upspeed='''$UP''', downlocalip='''$downlocalip''', downremoteip='''$downremoteip''', uplocalip='''$uplocalip''', upremoteip='''$upremoteip''' WHERE primkey=1"
構文エラーが発生します。
Error: near ".2": syntax error
設定したらローカルIPダウンロード10.1でのみうまく機能するので、追加の小数点が好きではありません。
テーブル自体で型をテキストに設定したので、それは重要ではないと思いますか?
テーブルのプラグマ出力:
0|primkey|integer|0||1
1|downspeed|integer|1||0
2|upspeed|integer|1||0
3|downlocalip|text|1||0
4|downremoteip|text|1||0
5|uplocalip|text|1||0
6|upremoteip|text|1||0
さまざまな見積もりを設定してみましたが、何が間違っているのかわかりません。
どんなアイデアがありますか?
編集する:
以下のコメントに基づいて試した完全なコマンドは次のとおりです。
/usr/bin/ssh [email protected] 'sqlite3 /var/www/server/newserverstats.db "UPDATE stats SET downspeed=$DN, upspeed=$UP, downlocalip="$downlocalip", downremoteip="$downremoteip", uplocalip="$uplocalip", upremoteip="$upremoteip" WHERE primkey=1"'
または
/usr/bin/ssh [email protected] 'sqlite3 /var/www/server/newserverstats.db "UPDATE stats SET downspeed=$DN, upspeed=$UP, downlocalip='$downlocalip', downremoteip='$downremoteip', uplocalip='$uplocalip', upremoteip='$upremoteip' WHERE primkey=1;"'
どちらも私に次のエラーを与えます。
Error: near ",": syntax error
新しいコマンド、詳細:
ssh [email protected] sqlite3 /var/www/server/newserverstats.db <<END_SQL
UPDATE stats
SET downspeed=$DN,
upspeed=$UP,
downlocalip="$downlocalip",
downremoteip="$downremoteip",
uplocalip="$uplocalip",
upremoteip="$upremoteip"
WHERE primkey=1
END_SQL
テストスクリプトの1行に戻ります。
#!/bin/bash -x
DN=123
UP=123
downlocalip=10.1.2.3
downremoteip=123
uplocalip=123
upremoteip=123
sql="UPDATE stats SET downspeed=$DN, upspeed=$UP, downlocalip="$downlocalip", downremoteip="$downremoteip", uplocalip="$uplocalip", upremoteip="$upremoteip" WHERE primkey=1"
echo $sql
ssh [email protected] sqlite3 /var/www/server/newserverstats.db "$sql"
これにより、次の応答が提供されます。
UPDATE stats SET downspeed=123, upspeed=123, downlocalip=10.1.2.3, downremoteip=123, uplocalip=123, upremoteip=123 WHERE primkey=1
sqlite3: Error: too many options: "stats"
Use -help for a list of options.
答え1
問題はテキストフィールドの文字列参照にあります。
ここにある文書を使用してください(もっと素敵な文章を書くことができます):
sqlite3 database <<END_SQL
UPDATE stats
SET downspeed=$DN,
upspeed=$UP,
downlocalip="$downlocalip",
downremoteip="$downremoteip",
uplocalip="$uplocalip",
upremoteip="$upremoteip"
WHERE primkey=1
END_SQL
これは、変数値が正しく削除され、SQLインジェクションの脆弱性が発生していないことを確認するために変数値を完全に制御できると想定しています。
コメントから:
SSHを介してこれを行います。
ssh user@server sqlite3 database <<END_SQL
UPDATE stats
SET downspeed=$DN,
upspeed=$UP,
downlocalip="$downlocalip",
downremoteip="$downremoteip",
uplocalip="$uplocalip",
upremoteip="$upremoteip"
WHERE primkey=1
END_SQL
答え2
主な問題は、各変数の前後に1つの単一引用符ではなく3つの単一引用符を使用することです。これは必ずしも必要ではありません。実際には動作しません。
実際に引用されていないため、IPアドレスにエラーが発生するため、$downlocalip
sqlite3はこれをテキスト文字列ではなく浮動小数点として解釈しようとします...浮動小数点には2つの小数点がありません。
もう一つの小さな問題は、整数フィールド(downspeed
および)upspeed
の値の周りに一重引用符を入れることです。
この試み:
sqlite3 /var/www/server/newserverstats.db "UPDATE stats SET downspeed=$DN,
upspeed=$UP, downlocalip='$downlocalip', downremoteip='$downremoteip',
uplocalip='$uplocalip', upremoteip='$upremoteip' WHERE primkey=1;"
この文字列の一重引用符は次のとおりです。~へ二重引用符は、シェルが変数を拡張するのを妨げません。二重引用符の中には特別な意味がなく、テキストの一部にすぎません。二重引用符内の変数は特別な意味を持つので、意図したとおりに拡張してください。
または、Kusalalanandaの答えでheredocを使用してください。もっと読みやすいです。
しかし、多くの場合、sqliteタスクを実行する場合は、プレースホルダ値をサポートするsqliteライブラリモジュールを持つ言語でスクリプトを作成するのが最善です。たとえば、どちらもsqlite3および他のSQLデータベースを操作するための優れたライブラリをperl
備えています。python
これらのライブラリを使用してコードを作成すると、ほとんど変更を加えずに他のデータベース(postgresqlやmysqlなど)と連携できます。