首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用带空格的路径名变量来构造新的命令变量而不破坏最终命令?

使用带空格的路径名变量来构造新的命令变量而不破坏最终命令?
EN

Unix & Linux用户
提问于 2022-02-25 06:52:16
回答 1查看 79关注 0票数 0

我读过许多关于shell引用和文件名中空格的其他问题,这些建议在这种情况下似乎行不通。

Putting一个带有字符串的变量,在另一个变量un-中包含一个转义空间,它将在最终输出中转义空间。

此脚本从用户输入和硬编码值组合一个命令,显示存储在变量中的命令,然后运行它:

代码语言:javascript
复制
#!/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是一个未知的参数。

我也尝试过:

代码语言:javascript
复制
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变量中路径名中的空格转义的正确语法是什么,以便当<#>stays被添加到包含最终命令的变量中时,location转义了

EN

回答 1

Unix & Linux用户

回答已采纳

发布于 2022-02-25 08:00:26

这一点:

$install_cmd;

是调用split+glob运算符对$install_cmd的内容,并希望得到的单词形成一个简单的命令的预期参数,这几乎没有意义。

在这里,您可能希望用bash语言以连接的部分构建代码,并最终告诉shell用eval来解释它,这很危险,因为很难避免命令注入漏洞。这必须是:

代码语言:javascript
复制
  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:Running:输出,以显示shell将通过eval解释哪些代码以及将运行什么结果命令。运行将使用一些execve("/path/to/virt-install", ["virt-install", "-n"...], environ)系统调用,然而,bash's xtrace输出将呈现为某些shell代码,如果由bash解释,这些代码将导致相同的系统调用。

或者使用可以容纳多个参数的变量类型构建简单命令的参数:数组,并调用由该数组元素组成的命令:

代码语言:javascript
复制
  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的第一个参数是格式。它不应该包含可变数据。

没有对shell代码的双重解释,这避免了命令注入漏洞的风险,因此更可取。

票数 1
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/692078

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档