
シェルの引用とファイル名の空白に関する他の多くの質問を読みましたが、これらの提案はこの場合は機能しないようです。
エスケープされたスペースを含む文字列を含む変数を別の変数に入れると、最終出力でスペースがエスケープ解除されます。
スクリプトは、ユーザー入力とハードコードされた値に基づいてコマンドを組み合わせ、変数に保存されているコマンドを表示して実行します。
#!/bin/bash
memory="4096"
cpus="--cpu=host --vcpus=2"
type="--os-type=linux"
variant="--os-variant=debiantesting"
graphics="--graphics spice"
network="--network bridge=vmbr0"
disk="--disk path=/dev/$chosen_vg_name/$lv_name"
#This line is the problem:
location="--cdrom /share/media/Linux\ ISO/debian11-server.iso";
# Run the command based on the supplied variable values:
install_cmd="virt-install -n $vm_name --memory $memory $cpus $type $variant $disk $location $graphics $network";
printf "$install_cmd\n";
$install_cmd;
exit 0;
私は何が起こったのか理解しています。変数内のファイルパスのスペースは、location
変数に追加されたときにエスケープされないため、コマンドでは不明な引数と見なされますinstall_cmd
。virt-install
ISO/debian11-server.iso
私も次のことを試しました。
location='--cdrom /share/media/Linux ISO/debian11-server.iso';
location="--cdrom "/share/media/Linux ISO/debian11-server.iso"";
location='--cdrom /share/media/Linux\ ISO/debian11-server.iso';
location='--cdrom /share/media/Linux\\ ISO/debian11-server.iso';
location="--cdrom /share/media/Linux\\ ISO/debian11-server.iso";
location
変数パス名からスペースをエスケープする正しい構文は何ですか?まだ脱出するlocation
最後のコマンドを含む変数にいつ追加されますか?
答え1
それ:
$install_cmd;
何かについてSplit + Glob演算子を呼び出し、結果の単語が単純なコマンドの予想されるパラメータを形成すると期待する$install_cmd
ことはほとんど意味がありません。
bash
ここでは、リンクされたセクションの言語でコードを記述し、最終的にシェルにそれを解釈するように指示できますeval
。これは、コマンド注入の脆弱性を避けるのが難しいため危険です。これは次のようになります。
memory=4096
cpus='--cpu=host --vcpus=2'
type='--os-type=linux'
variant='--os-variant=debiantesting'
graphics='--graphics spice'
network='--network bridge=vmbr0'
disk='--disk "path=/dev/$chosen_vg_name/$lv_name"'
location='--cdrom "/share/media/Linux ISO/debian11-server.iso"'
install_cmd="virt-install -n $vm_name --memory $memory $cpus $type $variant $disk $location $graphics $network"
printf >&2 'Interpreting: %s\n' "$install_cmd"
eval "(PS4='Running: '; set -o xtrace; $install_cmd)"
(この場合は$chosen_vg_name/$lv_name
拡張方法を確認してくださいeval
。)
上記では、シェルが解釈するコードと実行される結果コマンドを示すために、いくつかの内容Interpreting:
と出力を追加しました。実行は一部のシステムコールを使用して実行されますが、出力は bash で解釈されると同じシステムコールが発生する一部のシェルコードでレンダリングされます。Running:
eval
execve("/path/to/virt-install", ["virt-install", "-n"...], environ)
bash
xtrace
または、複数のパラメータを保持できる変数タイプを使用して、単純なコマンド(配列)のパラメータを構築し、その配列の要素で構成されたコマンドを呼び出します。
memory=4096
cpus=(--cpu=host --vcpus=2)
type=(--os-type=linux)
variant=(--os-variant=debiantesting)
graphics=(--graphics spice)
network=(--network bridge=vmbr0)
disk=(--disk "path=/dev/$chosen_vg_name/$lv_name")
location=(--cdrom '/share/media/Linux ISO/debian11-server.iso')
install_cmd=(
virt-install -n "$vm_name" --memory "$memory"
"${cpus[@]}" "${type[@]}" "${variant[@]}" "${disk[@]}"
"${location[@]}" "${graphics[@]}" "${network[@]}"
)
(PS4='Running: '; set -o xtrace; "${install_cmd[@]}")
(ここで$chosen_vg_name/$lv_name
配列に割り当てると展開されます$disk
)。
また、最初のパラメータprintf
は次のとおりです。滞在。変更可能なデータを含めないでください。
シェルコードには二重の解釈がないため、コマンドインジェクションの脆弱性のリスクを防ぐため、望ましい。