V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
sunjourney
V2EX  ›  程序员

Shell 编程问题,怎么保证脚本的执行环境在没污染的环境下?

  •  
  •   sunjourney · 2017-04-19 11:06:14 +08:00 · 3031 次点击
    这是一个创建于 2774 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在 shell 里给自己写的程序加了 alias wc=count ,但 count 的用法和 wc 不同 ,另外一个以前写的脚本用到了 wc, 现在执行会报错,它错误地使用了 count 。怎么使使这个以前的脚本一定用的是 wc 而不是我现在的 count 。其实我 tr 也被 alias 到了 tr=translate,也有使用的问题

    这段脚本大概是这样:

    res=$(echo $0 | grep '^pass' | wc -l | tr -d ' ')
    

    感觉和上下文有关吧?怎么让以前这个程序处在没有加 alias 的环境下呢?

    第 1 条附言  ·  2017-04-19 12:24:53 +08:00
    有一点很重要,补充一下,用了 wc, tr 的脚本写在 zsh 的 主题文件下,都是通过 source 执行,因此会读到被 alias 到的程序。
    25 条回复    2017-04-19 15:45:56 +08:00
    snip
        1
    snip  
       2017-04-19 11:17:37 +08:00
    使用原始路径,例如 /usr/bin/cp
    expy
        2
    expy  
       2017-04-19 11:19:35 +08:00
    \wc \tr
    vjnjc
        3
    vjnjc  
       2017-04-19 11:19:52 +08:00
    占楼同问,比如我的脚本用了 alias wc=count 这污染了环境,正确的方法是不是在退出前用 unalias ?
    Jisxu
        4
    Jisxu  
       2017-04-19 11:20:09 +08:00
    unalias -a

    > man:
    unalias [-a] [name ...]
    Remove each name from the list of defined aliases. If -a is supplied, all alias definitions are removed. The
    return value is true unless a supplied name is not a defined alias.
    xiaket
        5
    xiaket  
       2017-04-19 11:25:34 +08:00
    没人觉得你这样 alias 是有问题的咩? 如果觉得 count 和 translate 太长, 你应该 alias 到 c 和 t 或者, 让用途明显一点, mywc 和 mytr 嘛.
    knightdf
        6
    knightdf  
       2017-04-19 11:25:46 +08:00
    env
    sunjourney
        7
    sunjourney  
    OP
       2017-04-19 11:37:57 +08:00
    @snip #1
    @expy #2

    类似的用法查过了。可以 \wc, 'wc', "wc", command wc ,但是其它的部分可以保证安全吗?有一天我 sb 了把 if , while 全 alias ,其它程序都崩了呢?

    @knightdf #6 env 具体怎么做呢?
    sunjourney
        8
    sunjourney  
    OP
       2017-04-19 11:42:00 +08:00
    @xiaket #5 假如 c , t 被是原生的命令并且被其它的脚本用到了呢?感觉 shell 的程序与外部环境依赖太严重了,外部的状况很容易影响到 shell script 的执行结果。真有设计失败的感觉
    xderam
        9
    xderam  
       2017-04-19 11:48:41 +08:00
    别去改 root 的 alias ,自己用自己的 alias 就好了。这个不是设计失败,应该是使用习惯不好。 linux 设计的是多用户环境,环境之间本来就有”隔离“
    sunjourney
        10
    sunjourney  
    OP
       2017-04-19 12:01:42 +08:00
    @xderam #9 说说实际的情况吧,有一个程序,用到了 wc, tr ,有另一个程序,给 git 加别名。加别名的程序读入别名 $prefix , 执行 alias {$prefix}c='git commit', alias {$prefix}r='git remote', alias {$prefix}f='git fetch'
    正常嘛,$prefix 传入的是 g ,此时 gc='git commit', gr='git remote',但现在想给 $prefix 传入 t,结果 tr 就变成了 git remote , 用到了 tr 的程序就废了。同理 $prefix 是 w, i ,这时 if, wc 都不能用了。我希望 alias 东西只影响用户自己的执行环境,用其它的脚本,它们内部用的 if ,wc, tr 还是上层环境的。全部写成 \wc \tr 是不实际的,\if 也不能这么用。
    knightdf
        11
    knightdf  
       2017-04-19 12:02:10 +08:00
    @sunjourney man env
    erobot
        12
    erobot  
       2017-04-19 12:09:48 +08:00
    @sunjourney 测试了一下, alias 是不会影响到子 shell 的,难道你是 . script.sh 或者 source script.sh 来执行脚本的??
    sunjourney
        13
    sunjourney  
    OP
       2017-04-19 12:22:49 +08:00
    @erobot #12 程序写在 zsh 的 theme 里, zsh 的 theme 都是靠 source 执行,所以就这样了。
    xiaket
        14
    xiaket  
       2017-04-19 12:37:28 +08:00
    @sunjourney 前面已经有人说了, 这不是设计失败, 是你的使用习惯问题. 另外, 我刚才列出 c 和 t 就是因为 a-z 都不是广为人知的系统命令.

    另外, 不管是用 OSX/Windows/Linux, 用户自己要作死, 操作系统都是拦不住的.
    sunjourney
        15
    sunjourney  
    OP
       2017-04-19 13:22:35 +08:00
    @xiaket #14 那具体问题怎么解决, oh-my-zsh.sh source 的主题遇到了被 alias 掉的命令(比如 Soliah.zsh-theme , date , git ,一旦被 alias )使用都会出错,可有解决方法?
    geelaw
        16
    geelaw  
       2017-04-19 13:42:03 +08:00
    答案是不要这么做就好了——不要 override 系统中默认的 aliases 和 names ,也不要在脚本里面创造 aliases 。

    何必要创造问题呢?
    sunjourney
        17
    sunjourney  
    OP
       2017-04-19 13:51:20 +08:00
    @geelaw #16 嗯,只是想探讨问题而已,现在已经确定了此题无解,在程序里加了一个 warning 告知动态设定 alias 的方法对 source 到环境中的 function 与 rc scripts 有影响。
    fxxkgw
        18
    fxxkgw  
       2017-04-19 14:07:50 +08:00
    LC_ALL=C
    rrfeng
        19
    rrfeng  
       2017-04-19 14:43:42 +08:00
    用已存在的名字当作 alias 是一种什么奇怪的想法呢……
    momocraft
        20
    momocraft  
       2017-04-19 14:50:30 +08:00
    防御性编程: 在开头把需要的东西都 type 一遍,有 alias 就报错退出

    当然人总是可以作死的,比如可能有人把 type 也 alias 掉。

    不如一开始就不用容易搞出事的做法。
    sunjourney
        21
    sunjourney  
    OP
       2017-04-19 14:57:23 +08:00
    @rrfeng #19
    @momocraft #20
    这个功能就是这样,定义了 alias ${prefix}c='git commit',
    先用一个 function 将参数给 $prefix ,在 source alias ${prefix}c='git commit'
    $prefix 默认是 g ,但用户就是传入 w ,自然就变了了 alias wc='git commit',然后出现问题。
    lululau
        22
    lululau  
       2017-04-19 15:11:31 +08:00   ❤️ 1
    没记错的话, alias 在 non-interactive shell 里是不会被展示的。。。

    man bash | col -b | grep -i 'alias.*interactive'

    另外,强制调用 external command:

    command my_cmd
    vingz
        23
    vingz  
       2017-04-19 15:12:39 +08:00
    我从来不用 alias ,脚本的话,一次编写,多次执行,所以没必要用 alias 省事吧
    vingz
        24
    vingz  
       2017-04-19 15:13:18 +08:00
    env 可以修改环境变量,并且只对本次命令执行生效,可以解决你的问题
    xderam
        25
    xderam  
       2017-04-19 15:45:56 +08:00
    @sunjourney alias {$prefix}c='git commit' 一个胶水语言别搞那么复杂了,如果真想纠结这个问题。我记得内部命令的执行顺序是第一,然后是 PATH 里的,然后是 alias ?记不太清楚了。可以搞本鸟哥的书看看。
    如果是生产环境,别搞那么灵活。小心出现 rm -rf $var 的例子。 自己测试环境无所谓了,写个 if 判断下,或者直接写死吧。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4417 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 04:05 · PVG 12:05 · LAX 20:05 · JFK 23:05
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.