虎绿林HU60.CN
发现版块
Enter
发布登录
发现版块发布我的社区荣誉
登录
虎绿林让技术讨论持续生长
主题Jhin经典
京ICP备18041936号-1

请问为什么下面的linux命令不能生效?

弟
弟妹
2022年8月16日 · 2022年8月16日编辑Linux/Unix
11.6万 21

需求场景:

通过编程方式启动一个子进程,临时更改用户python命令的指向。
所以我想到了别名方式。想临时覆盖用户原有的python命令

实际思路:

  1. 一条命令完成设置别名,并且使用别名命令【失败】
$ alias python=python2;python --version

显示python ,找不到该命令。
不关闭shell,下一行输入lll ,别名是可以生效的。
但是 并不能做到我一条命令临时覆盖lll的命令。

  1. 多条命令设置别名以及使用别名命令【失败】
    执行完alias python=python2以后 流就关闭了,我无法再write输入流,让其模拟输入下一条命令的操作

请教大佬有没有其他解决方案

登录后收藏
楼层讨论

21 条回复

默认正序
无
无名啊2022年8月16日
#1

Bash 手册里,Alias 条目说:

Bash always reads at least one complete line of input, and all lines that make up a compound command, before executing any of the commands on that line or the compound command. Aliases are expanded when a command is read, not when it is executed. Therefore, an alias definition appearing on the same line as another command does not take effect until the next line of input is read. The commands following the alias definition on that line are not affected by the new alias.

大意:

Bash 总是至少读取完整的一行(或多行,保证复合命令也读完整咯),接着立即扩展别名,最后再执行命令

另外,你的ls -ll需要用引号括起来,否则-ll不是lll的一部分,而是成为alias的参数。如:

$ alias lll='ls -ll'
弟
弟妹2022年8月16日
#2
并不行哦
ubuntu@ubuntu:~$ alias lll='ls-ll';lll

Command 'lll' not found, did you mean:

  command 'llc' from deb llvm
  command 'dll' from deb brickos
  command 'llt' from deb storebackup
  command 'lli' from deb llvm-runtime

Try: sudo apt install <deb name>
无
无名啊2022年8月16日
#3

@弟妹,看来你是没看懂大意,也没看英文原文呐。。

弟
弟妹2022年8月16日
#4
@无名啊,抱歉 我不是用我举得例子测试的。我现在明白了,不加引号,是参数没有携带。并且会提示alias 没有ll参数
现在明白你引用的大意了,所以我补充了我的需求场景,明白alias不符合我的要求了
无
无名啊2022年8月16日
#5

@弟妹,

  1. Bash 总是至少读取完整的一行

    读取alias lll='ls -ll';lll

  2. 接着立即扩展别名

    alias不是别名,lll也不是别名(你的alias lll='ls-ll'此时还未执行),所以不用扩展

  3. 最后再执行命令

    1. 执行alias lll='ls -ll'
    2. 执行lll
弟
弟妹2022年8月16日
#6
@无名啊,是的 因为我是子进程打开的shell 我无法做到输入两条命令,因为我不是在tty下进行输入的
无
无名啊2022年8月16日
#7

@弟妹,

Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt.

需要在交互式模式,或者启用expand_aliases,alias才能生效

无
无名啊2022年8月16日
#8

@弟妹,

多条命令设置别名以及使用别名命令【失败】

贴下代码?

弟
弟妹2022年8月16日
#9

@无名啊,以Node.js 创建子进程为例

import * as child from 'child_process'

export async function execRequest(cmd: string, commands: string[]) {
    return new Promise((resolve) => {
        let spawnChild = child.spawn(cmd)
        spawnChild.stdout.on('data', ch => {
            console.log(ch.toString().trim())
        })
        spawnChild.stderr.on('data', ch => {
            console.log(ch.toString().trim())
        })

        spawnChild.on('exit', code => {
            console.log(code)
        })

        commands.forEach((command) => {
            spawnChild.stdin.write(`${command}\n`)
        })

        spawnChild.stdin.end('\nexit\n')
    })
}

await execRequest('bash',['alias python233=python2','python233 --version 2>&1'])

以上代码 大概意思是,输入bash,并开启交互式shell

第一次流写入alias python233=python2 并且回车
第二次流写入python233 --version 2>&1 并且回车
输出流提示
提示python233不存在
PS: python --version竟然输出到错误流 真离谱

无
无名啊2022年8月16日
#10

@弟妹,看来,你没看 7 楼

await execRequest('bash',['shopt -s expand_aliases', 'alias python233=python2', 'python233 --version 2>&1'])
无
无名啊2022年8月16日
#11

@弟妹,

PS: python --version竟然输出到错误流 真离谱

我瞅了瞅,应该是输出至stdout的?

$ python3 --version | sed 's/^/[STDOUT] /'
[STDOUT] Python 3.10.5
弟
弟妹2022年8月16日
#12
@无名啊,我知道7楼这个方案,因为机器没网,电脑里没有这个软件。所以就没采用这个。。。

使用的交互式shell,是不好用的。

然后,我是拿python2.7测试--version输出到错误流的(我还没测试其他机器的2.7是否也这样)
无
无名啊2022年8月16日
#13

@弟妹,

噢,我看漏了这一句

并开启交互式shell

看来,你读了 7 楼的

只是,这nodejs代码里,哪一行是代表连接到了tty吗?(我不熟悉nodejs,但我还是能看得懂很多js的,即使是到ES2022)

无
无名啊2022年8月16日
#14

@弟妹,

因为机器没网,电脑里没有这个软件。所以就没采用这个。。。

Emm..?不需要额外安装啥软件呀,只是加一行bash代码

然后,我是拿python2.7测试--version输出到错误流的(我还没测试其他机器的2.7是否也这样)

我不熟悉Python 2,我电脑也没装,那就不清楚了

弟
弟妹2022年8月16日
#15
@无名啊,我是python2 2>file.err 这么测试的,sed我是不太会用
弟
弟妹2022年8月16日
#16
@无名啊,shopt 这个软件我电脑没有。。


22:50 测试发现,原来是我用的zsh没有。我没具体看这个报错,我明天再试试

shopt is not a command, but a shell built-in. bash knows what to do with it because it's a bash built-in , but zsh has no idea what it is. You'll want to look into setopt which is a zsh built-in, and put those values into a new .zshrc script.
无
无名啊2022年8月16日
#17

@弟妹,我觉得,你的nodejs应该只是提供了普通stdin,加上你又没用bash -i参数,所以启动的bash应该不是交互式的

这时你用 10 楼的代码,alias应该就能生效了

无
无名啊2022年8月16日
#18

@弟妹,你用的zsh啊。。这个我不熟悉,你需要@老虎会游泳 了

无
无名啊2022年8月16日
#19

@弟妹,shopt是bash的内置命令,不需要额外安装

而且你在nodejs里启动的也是bash,应该没问题?

$ type shopt
shopt is a shell builtin
弟
弟妹2022年8月16日
#20
@无名啊,好的,谢谢。我明天试试10楼的。
你写的那个参数,我之前查资料是bash这个shell才有的好像。zsh好像没有
shopt is not a command, but a shell built-in. bash knows what to do with it because it's a bash built-in , but zsh has no idea what it is. You'll want to look into setopt which is a zsh built-in, and put those values into a new .zshrc script.
弟
弟妹2022年8月17日
#21

@无名啊,加上shopt -s expand_aliases 可以了 谢谢大佬。

只是,这nodejs代码里,哪一行是代表连接到了tty吗?(我不熟悉nodejs,但我还是能看得懂很多js的,即使是到ES2022)

我的理解跟编程语言无关,我是fork出来的子进程来启动bash命令,这个bash命令不会立刻退出,可以等待我输入,我就可以输入流写入数据,我称它为“交互式” 😂(1. 也可能默认开启了tty 2.也可能没有收到终止信号,所以一直等待)

和实际 交互式登录SHELL 非交互式登录SHELL概念是否一样,我并没有仔细研究

加入这场讨论登录后即可参与讨论
登录并回复
关于作者弟弟妹骨灰

这位用户还没有留下个人签名。

查看用户主页
帖子信息
发布于2022/08/16 20:09
最后更新2022/08/17 09:56
阅读11.6万