【问题标题】:Bash Script - Run Functions with Variables in LoopBash 脚本 - 使用循环中的变量运行函数
【发布时间】:2012-01-17 23:42:16
【问题描述】:

我有一个按原样工作的共享备份 bash 脚本,但它使用几行来执行可以循环的操作(我希望如此)。我认为它可以更好,在我看来,第一步是使用循环来循环共享。

在当前状态下,我拥有的脚本为每个共享调用三个 bash 函数和一个 python 脚本(使用 stderr 和 stdout 发送电子邮件),其中有几个(现在 4 个,可能多达 6-8 个) ,它看起来像这样:

create_log_dir "$share1_backup"
create_log "$share1_backup" "$log_file"
create_rsync_cmd "$log_file"

python backup.py $email_address \
"$rsync_command $rsync_args $share1 $share1_backup"

因此,上面的代码对于所有共享来说大概是 20-30 行。我希望为每个看起来像这样的共享(类似伪代码的示例)创建一个遍历这些步骤的循环:

for var in list (each $share_var and $log_var)
do
  create_log_dir "$share_var"
  create_log "$share_var" "$log_var"
  create_rsync_cmd "$log_var"
done

我用一些 bash 选项尝试了这种格式,但无法正常工作。对 bash 来说还是新手,所以我希望能从中学到一些很酷的技巧。

提前致谢。

更新编辑

这里是路径和日志变量以及我正在使用的 for 循环:

#variables
share1="/path/to/share/"
share1_backup="/path/to/share/backup"

# log creation
# If the 'rsync_logs' directory in destination doesn't exist, create it.
create_log_dir()
{
   backup_dest=$1
   if [ ! -d "$backup_dest/rsync_logs" ]
   then
      mkdir $backup_dest/rsync_logs
   fi
}

# Check for log_file existence; append '_alt' if exists.
create_log()
{
   backup_dest=$1
   log_file=$2
   log_file="$backup_dest/rsync_logs/$(date +"%Y-%m%d")_rsync_output.log"
   if [ -f $log_file ]
   then
      log_file="${log_file}_alt"
   fi
}

#loop
for pair in "share1_backup log_file"
do
  set -- $pair
  share=$1
  log=$2

  create_log_dir "$share"
  create_log "$share" "$log"
  create_rsync_cmd "$log"
done

所以我用原来的答案试了一下:

for pair in "share1_backup log_file"

并且...使用变量方法(似乎都不起作用 - 第一个给出错误,因为目录 share1_backup/rsync_logs 不存在 - 它没有使用变量):

for pair in "${share1_backup} ${log_file}"

第二个导致空日志文件。

更新编辑 2

我认为更好的方法是在其他地方构建日志,以便下面的两个答案都有效。我最初认为将它们保存在备份目标中会很好,但话又说回来,最好将日志保存在安装了所有共享的机器上,以保持一致性。然后,如果我必须将它们放在目标驱动器上,我可以编写一个定期复制它们的脚本。这样,我可以提前构建 log_file 变量,然后在循环中使用它,正如 David K. Hess 指出的那样。

再次感谢。

【问题讨论】:

  • 你用什么list
  • 嗯,列表将是我的共享列表和日志变量。但它不一定是一个列表,我猜。不确定这是否是最好的方法???
  • 在您最新的脚本中,在第一种使用文字的情况下,它将使用这些确切的值作为您的函数的参数(这不是我认为您想要的)。在第二种情况下,您没有在 for 循环执行之前初始化“log_file”变量。
  • 嗯,我明白你的意思了……基于此,看来这个想法可能根本行不通;或者,至少,不像我想象的那样。我想我需要摆弄一些其他的想法。非常感谢您的帮助。

标签: bash function loops


【解决方案1】:

只要您的路径中没有空格,这种方法就应该有效:

for pair in "share1_var log1_var" "share2_var log2_var"
do
    set -- $pair
    share_var = $1
    log_var = $2
    create_log_dir "$share_var"
    create_log "$share_var" "$log_var"
    create_rsync_cmd "$log_var"
done

【讨论】:

  • 我正在考虑将其作为一个函数来尝试。在这种情况下,我会调用 run_functions "$share_name" "$log_name".$share_name 之类的东西 arg 1 和 $log_name arg 2。这仍然有效吗?我不熟悉配对概念,尽管它看起来很简单。
  • 我认为函数方法与您的基本困境正交 - 您需要遍历一个列表,其中每个项目由另外两个项目组成。因此,您仍然存在使用两个变量进行循环以进行函数调用的问题。当然,这在 Python 中都非常简单,因此您可能想查看 subprocess 模块并从 Python 执行您的命令。
  • 是的,在摆弄了一下之后,我意识到我是鸡和蛋。最初,这个 bash 脚本应该只是一个运行 python 脚本的容器。但是,既然您提到了它,那么将其中一些逻辑添加到 python 程序中或构建另一个来执行此操作可能是更好的方法。感谢您的建议。
  • David K. Hess:我的解决方案有问题。 for pair in "share1_var log1_var" 行似乎应该可以工作......我需要它来使用上面声明为路径的变量。所以我尝试了for pair in "${share1} ${log1_var}",我的日志文件最终为空。
  • 很难说 - 你能用最新版本的脚本更新你的问题吗?
【解决方案2】:

使用数组怎么样?即使您的值包含空格,它也有效。

array=("share1" "log1"
       "share2" "log2")
for ((i=0; i<${#array[@]}; i+=2)) ; do
    share_var=${array[i]}
    log_var=${array[i+1]}
    create_log_dir "$share_var"
    create_log "$share_var" "$log_var"
    create_rsync_cmd "$log_var"
done

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-09
    • 2013-09-17
    • 2019-07-20
    • 2018-10-09
    • 1970-01-01
    • 2011-07-07
    • 2022-01-04
    • 2012-06-28
    相关资源
    最近更新 更多