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

bashshell:避免使用别名来解释$!,bash,shell,alias,wait,Bash,Shell,Alias,Wait,我创建了一个别名: alias my_rsync = "rsync -av ${PATH_EXCLUDE_DEV} ${PATH_SYS_DEV}/` ${PATH_SYS_SANDBOX}/ && wait $! && cd - &>/dev/null\" 当加载此别名并使用命令“键入my\u rsync”查看它时,我看到$!因为它被解释了,所以它消失了 通常我会用反斜杠逃逸,它的功能很好。例如: alias my_rsync = "mysql

我创建了一个别名:

alias my_rsync = "rsync -av ${PATH_EXCLUDE_DEV} ${PATH_SYS_DEV}/` ${PATH_SYS_SANDBOX}/ && wait $! && cd - &>/dev/null\"
当加载此别名并使用命令“键入my\u 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
调用没有任何意义

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

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都运行时遍历该数组以完成它们


值得注意的是,正是单个
&
操作符导致
rsync
在后台运行。如果使用
和&
将它们与以下命令分开,
或换行符,它们将一次运行一个,并且
$的值永远不会被更改。

为什么要在一个没有后台的进程上等待
呢?还是因为格式不稳定,我误解了?你能改进你的格式吗?bash不是Bourne。就这一点而言,
/bin/sh
也不是现代系统的伯恩
/bin/sh
是POSIX sh,一个90年代的规范,很大程度上源自ksh,而不是70年代的伯恩。如果你不想解释它,就逃避它……但是<代码>等待$在这里没有意义。您没有任何背景,因此没有
$(由最后一个后台PID填写)设置在别名中的任何位置…现在,在另一个点上,如果文件名中有空格,或者试图引用变量中参数中的任何内容,缺少引号将导致一系列错误。请参阅BashFAQ#50:使用$!,此解决方案在bourne shell中不起作用。是的。张贴完整的example@user3332010,Bourne的哪个实现?Real 70年代的Bourne(据我所知,除了Sun之外,其他操作系统供应商几十年来都没有提供过它,Sun在Solaris 11中仅用POSIX sh替换了它),或者您实际使用的是POSIX sh(如果是的话,是哪种实现)?总的来说,我确实希望这个答案表现正确。传家宝Bourne(源于OpenSolaris代码,因此源于Sun的SVR4代码库)似乎根本不支持别名(在OS X上运行时,
alias
命令引用
/usr/bin/alias
,而不是由内置实现)。@CharlesDuffy:GNU bash,版本4.2.53(1)-发行版(i686 pc linux GNU)