Linux环境中alias不生效问题

很多时候,实际结果往往和我们的预期不一致,其中必有蹊跷。。。

问题

由于公司hadoop集群迁移,需要对线上几百台历史遗留的脚本进行改造,变更hadoop客户端环境。

思虑再三,借鉴python装饰器的思想,部署一个绿色版的hadoop客户端环境。再将线上各式各样的脚本统一加一行alias hadoop="/path/to/hadoop"成本最低。

无奈alias貌似并没有生效,实际操作结果和预期不一致。。。

结果

alias 在非交互shell环境中不生效,除非手动设置shopt -s expand_aliases

验证

  • cat aliasVerifi.sh

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    #/bin/bash
    shopt |grep -i alias
    whoami
    which whoami
    echo "================"
    shopt -s expand_aliases
    shopt |grep -i alias
    alias whoami='date "+%Y-%m-%d %H:%M:%S"'
    whoami
    which whoami
  • 通过cron调用脚本并将输出写入log文件aliasVerifi.log

  • cat aliasVerifi.log

    1
    2
    3
    4
    5
    6
    7
    expand_aliases 	off
    root
    /usr/bin/whoami
    ================
    expand_aliases on
    2018-11-06 22:20:01
    /usr/bin/whoami
    • 此处我们注意到expand_aliases在非交互shell中默认关闭,并且用which获取该命令的绝对路径并没有发生改变,但是执行结果已经符合预期。

其它说明

  • 当alias的命令和sudo一起使用时alias命令不生效,此时将sudo加入alias中即可生效。

    1
    2
    3
    4
    5
    6
    7
    $ alias mkdir='mkdir -p'
    $ sudo mkdir 1/2/3
    mkdir: cannot create directory ‘1/2/3’: No such file or directory
    $ mkdir 1/2/3
    mkdir: cannot create directory ‘1’: Permission denied
    $ alias mkdir='sudo mkdir -p'
    $ mkdir 1/2/3
    1
    2
    3
    4
    5
    $ alias mv='/usr/bin/mv -v -b -S $(date "+.mvbak%Y%m%d_%H%M")'
    $ sudo mv a.sh b.sh
    $ alias mv='sudo /usr/bin/mv -v -b -S $(date "+.mvbak%Y%m%d_%H%M")'
    $ mv a.sh b.sh
    ‘a.sh’ -> ‘b.sh’
    • 前提,mkdir,mv命令已加入sudoers
  • 在xargs命令后命令别名也不生效,因为xargs是一个单独的应用程序,它不是shell,因此没有别名或函数的概念。但可以通过以下两种方式变相使用alias

    • xargs ${BASH_ALIASES[alias_command]}
      • ${BASH_ALIASES[alias_command]}前后不能有引号
    • xargs -t -i bash -ic “alias_command }”
    • ansible script中可以使用alias,但是xargs后面的变量${BASH_ALIASES[alias_command]}为空,不能被使用。
  • 在sshpass命令后命令别名同样不生效

    • 以下情况不生效alias rsync不生效

      1
      2
      3
      export SSHPASS="xxxx"
      alias rsync='rsync -e "ssh -q -o StrictHostKeyChecking=no" -avzP'
      sshpass -e rsync ...
    • 可用以下方式变相实现

      1
      2
      3
      export SSHPASS="xxxx"
      alias rsync='sshpass -e rsync -e "ssh -q -o StrictHostKeyChecking=no" -avzP'
      rsync ...
  • 脚本中使用alias命令别名,通过eval调用命令别名可以生效。

参考文档