bash shell: 避免使用别名来解释 $!

bash shell: Avoid alias to interpret $!

我创建了一个别名:

alias my_rsync = "rsync -av ${PATH_EXCLUDE_DEV} ${PATH_SYS_DEV}/` ${PATH_SYS_SANDBOX}/ && wait $! && cd - &>/dev/null\"

什么时候加载这个别名并用命令观察它 'type my_rsync' 我看到 $!已消失,因为它已被解释。

通常我会用反斜杠转义,而且效果很好。例如:

alias my_rsync = "mysql ${DB_DATA_SYS_SANDBOX} -e 'SHOW TABLES' | grep -v 'Tables_in_${DB_NAME_SANDBOX}' | while read a; do mysql ${DB_DATA_SYS_SANDBOX} -e \"DROP TABLE $a\";done"

你们能给我点提示吗?谢谢

如果您不想解释某个变量,请将其转义或使用单引号。

示例:

$ alias x="false; echo $?"
$ x
0

$ alias x='false; echo $?'
$ x
1

使用函数,而不是别名,您可以完全避免这种情况。

my_rsync() {
  # BTW, this is horrible quoting; run your code through http://shellcheck.net/.
  # Also, all-caps variable names are bad form except for specific reserved classes.
  rsync -av ${PATH_EXCLUDE_DEV} ${PATH_SYS_DEV}/ ${PATH_SYS_SANDBOX}/ &>/dev/null
  cd -
}

...在这个公式中,在函数被扩展之前不会发生任何扩展。


至于 wait -- 只有当您 运行 在后台进行操作时才有意义。您在此处的用法不会在后台启动任何内容,因此 wait 调用没有任何意义。

另一方面,下面显示了一些 有目的的等待调用:

rsync_args=( --exclude='/dev/*' --exclude='/sys/*' )
hosts=( foo.example.com bar.example.com )

my_rsync() {
  # declare local variables
  declare -a pids=( ) # array to hold PIDs
  declare host pid    # scalar variables to hold items being iterated over

  for host in "${hosts[@]}"; do
    rsync -av "${rsync_args[@]}" /sandbox "$host":/path & pids+=( "$!" )
  done

  for pid in "${pids[@]}"; do
    wait "$pid"
  done
}

这运行在后台同时进行多个rsync(每个主机一个),将它们的PID存储在一个数组中,然后在它们都存在时遍历该数组运行 让他们完成。

值得注意的是,正是 单个 & 运算符 导致 rsync 在后台变为 运行。如果它们用 &&; 或换行符与以下命令分开,它们将一次 运行 一个,而 $! 的值永远不会是改变了。