0

我正在编写一个 bash 脚本来调用 Veeam Backup CLI 的函数。

在这个脚本中,我有一个配置新备份作业的功能。

function configureBackupJob() {

    jobname="$1"
    reponame="$2"
    objects="$3"
    advancedOptions="$4"
    scheduleOptions="$5"
    activeFullBackupOptions="$6"
    indexingOptions="$7"


    command="veeamconfig job create filelevel --name ${jobname} --reponame ${reponame} --includedirs ${objects} ${advancedOptions} ${scheduleOptions} ${activeFullBackupOptions} ${indexingOptions} --nosnap"
    echo "${command}"

    veeamconfig job create filelevel --name "$jobname" --reponame "$reponame" --includedirs "$objects" "$advancedOptions" "$scheduleOptions" "$activeFullBackupOptions" "$indexingOptions" --nosnap

}

在调用脚本时,我使用一个案例来确定应该调用哪个函数:

case $command in
    # More cases before and after this one
    configureBackupJob)
        configureBackupJob "$2" "$3" "$4" "$5" "$6" "$7" "$8"
        ;;
    *)
        showHelp
        ;;
esac

我这样调用脚本:

sudo ./script.sh configureBackupJob "TheJobsName" "RepositoryName" "/path/FoldertoBeBackedUpByVeeam"  "--daily --at 12:15" "--weekdays-full Monday,Wednesday" "--indexall"

我使用 Veeam 帮助中心的这个网站来了解这些参数:Veeam 帮助中心:创建文件级备份作业

调用脚本会导致错误消息

Unknown argument: [--daily --at 12:15].

如果我手动调用 veeamconfig,我的 echo 显示的命令可以正常工作。

为什么我可以直接调用命令而不是从脚本中调用?我尝试在没有双引号的情况下调用该函数,但这不起作用。

我不能硬编码所有的论点,比如

--includedirs

所以我需要找到一种方法来传递参数,比如

--daily --at 12:15
4

1 回答 1

1

基本问题是您将“ ”作为单个参数传递--daily --at 12:15给命令,而不是三个单独的参数(“ ”、“ ”和“ ”)。这让人困惑。当你这样做时它看起来没问题,因为这失去了参数之间的空格和参数中的空格之间区别。veeamconfig--daily--at12:15veeamconfigecho

处理此问题的最佳方法取决于几件事:首先,您的脚本是否关心哪些选项与调度、索引、完整备份和其他任何内容有关,或者如果只有一个选项列表可以提供给veeamconfig命令?其次,路径/选项/任何内容是否可能包含空格(或文件名通配符)以及它们之间?(注意:我主要使用 macOS,其中带有空格的路径非常常见。)

如果脚本不需要区分不同类型的选项,这很简单:只需将所有选项作为单独的参数一直传递,并在必要时将它们存储为数组而不是单独的字符串(并使用bash正确引用/转义打印命令选项的选项)printf%q

function configureBackupJob() {

    jobname="$1"
    reponame="$2"
    object="$3"
    allOptions=("${@:4}")    # This stores all arguments starting with $4 in an array

    printf -v command '%q ' veeamconfig job create filelevel --name "$jobname" --reponame "$reponame" --includedirs "$object" "${allOptions[@]}" --nosnap
    echo "${command}"

    veeamconfig job create filelevel --name "$jobname" --reponame "$reponame" --includedirs "$object" "${allOptions[@]}" --nosnap
}

并这样称呼它:

case $command in
    # More cases before and after this one
    configureBackupJob)
        configureBackupJob "${@:2}"
        ...

并像这样运行整个脚本:

sudo ./script.sh configureBackupJob "TheJobsName" "RepositoryName" "/path/FoldertoBeBackedUpByVeeam"  --daily --at 12:15 --weekdays-full Monday,Wednesday --indexall

如果脚本需要区分不同类型的选项,事情就会变得更加混乱。如果选项中不可能有空格或类似通配符的字符,则可以在将这些变量传递给veeamconfig命令时不加引号,并让 shell 的分词将它们分解为单独的参数:

veeamconfig job create filelevel --name "$jobname" --reponame "$reponame" --includedirs "$objects" $advancedOptions $scheduleOptions $activeFullBackupOptions $indexingOptions --nosnap

请注意,如果您走这条路线,则需要在过程中的所有其他点安全地使用双引号,尤其是在将它们传递给configureBackupJob函数时。如果分词发生得太早,只会弄得一团糟。

如果您需要将选项类型分开在选项中允许空格和/或有趣的字符,那就更难了。您可能很想在选项中添加引号和/或转义符来控制它,但分词不尊重这些,因此它不起作用。我想我只会向您推荐这个问题,并希望这不适用。

于 2021-01-12T23:32:43.950 回答