スペースを含むパス名変数を使用して、最後のコマンドを中断せずに新しいコマンド変数を生成しますか?

スペースを含むパス名変数を使用して、最後のコマンドを中断せずに新しいコマンド変数を生成しますか?

シェルの引用とファイル名の空白に関する他の多くの質問を読みましたが、これらの提案はこの場合は機能しないようです。

エスケープされたスペースを含む文字列を含む変数を別の変数に入れると、最終出力でスペースがエスケープ解除されます。

スクリプトは、ユーザー入力とハードコードされた値に基づいてコマンドを組み合わせ、変数に保存されているコマンドを表示して実行します。

#!/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_cmdvirt-installISO/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:evalexecve("/path/to/virt-install", ["virt-install", "-n"...], environ)bashxtrace


または、複数のパラメータを保持できる変数タイプを使用して、単純なコマンド(配列)のパラメータを構築し、その配列の要素で構成されたコマンドを呼び出します。

  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は次のとおりです。滞在。変更可能なデータを含めないでください。

シェルコードには二重の解釈がないため、コマンドインジェクションの脆弱性のリスクを防ぐため、望ましい。

おすすめ記事