我想通过 SSH 登录到远程服务器 (Amazon Linux 2),同时执行su
一些命令,并在单个脚本中维护 SSH 会话,如下所示:
ssh -t ec2-user@$host -i $keypath \
'sudo -iu some-user bash -c "
echo a;
c(){ clear; };
echo b;
"'
输出:
a
b
Connection to xx.xx.xx.xx closed.
所以,一点点改进
ssh -t ec2-user@$host -i $keypath \
'sudo -iu some-user bash -c "
echo a;
c(){ clear; };
echo b;
bash -l;
echo c;
"'
输出:
a
b
(在此之后,我设法以用户:some-user 的身份通过 SSH 登录到远程并保持会话。)
然而,
# on the remote
$ whoami
some-user
$ c
bash: c: command not found
我想让c
命令在我以用户身份 SSH 登录后起作用:some-user。
我怎样才能解决这个问题?
注意:
1.
bash -l
是保持SSH会话存活。如果我删除它,我将被 SSH 注销
2.
我不想编辑任何像 ~/.bashrc 这样的 init 文件,因为我只想对我的 SSH 会话产生影响,而不是其他人的。
3. SSH登录后
我可以做alias c=clear
,是的,但是如果你想设置10个(功能的)别名并且你有10个不同的遥控器,那就很麻烦了。
4.
远程shell是/bin/bash
答案1
您的示例中没有任何内容显示别名工作或不工作。它可能实际上正在工作,只是你无法判断,而且无论如何它在那里也没用。
Alias 是 shell 内置命令,用于为当前 shell 设置 shell 别名。除了该 shell 的内存之外,它不会将该别名保存在任何地方。
如果您启动一个新 shell,它不会记住其他 shell 实例的任何别名。如果您想跨 shell 记住别名,则该别名需要位于 shell 初始化文件之一中。
更糟糕的是,像这样的命令以非交互式方式运行,并且许多 shell 初始化文件的结构不会为非交互式 shell 加载别名。此外,shell 加载哪些 init 文件会发生变化,具体取决于这是登录 shell、子 shell 还是暂时的非迭代 shell。此外,shell 选项可以显式禁止加载 init 文件。因此,如果您希望别名在非交互式 shell 中可用,则必须注意在哪个 shell 初始化文件中创建别名。
在这个组合中添加 sudo 会让事情变得更加混乱。您想在 root 的 shell 中使用该别名吗?然后它需要位于 root 的 shell 初始化文件中。
假设 bash 的 Linux 默认 shell 为交互式 shell,则~/.bashrc
每个想要使用别名的用户(包括 root)都可以使用别名。
答案2
别名很棘手。这是man bash
(强调我的)的相关部分:
有关别名的定义和使用的规则有些令人困惑。在执行该行或复合命令上的任何命令之前,Bash 始终读取至少一个完整的输入行以及构成复合命令的所有行。别名在读取命令时展开,而不是在执行命令时展开。 因此,与另一个命令出现在同一行的别名定义在读取下一行输入之前不会生效。该行上别名定义后面的命令不受新别名的影响。执行函数时,此行为也是一个问题。别名在读取函数定义时展开,而不是在执行函数时展开,因为函数定义本身就是一个命令。作为一个
,函数中定义的别名只有在执行该函数之后才可用。 为了安全起见,请始终将别名定义放在单独的行上,并且不要在复合命令中使用别名。对于几乎所有用途,别名都被 shell 函数取代。
这意味着,如果您想像这里一样在非交互式 shell 中使用别名,则需要使用以下命令显式启用别名shopt -s expand_aliases
和您需要将别名定义放在单独的行上。 A;
不会削减它,你需要一个实际的换行符:
## fails
$ ssh localhost 'alias ff="echo \"I am an alias!\""; ff'
bash: line 1: ff: command not found
## fails
$ ssh localhost 'alias ff="echo \"I am an alias!\""; shopt -s expand_aliases; ff'
bash: line 1: ff: command not found
## works
$ ssh localhost 'alias ff="echo \"I am an alias!\""; shopt -s expand_aliases;
> ff'
I am an alias!
这……确实不太可能是你想要的。首先,说实话,听起来您应该做的是将所有这些命令放入脚本中并运行该脚本,而不是摆弄这种非常复杂的方法。如果您坚持这样做,那么至少使用函数而不是别名:
$ ssh localhost 'ff(){ echo "I am a function!";}; ff'
I am a function!
看看这简单多了?
现在,您描述的错误和行为与您给我们的命令不匹配。但是,要运行您显示的命令,您可以使用函数执行类似以下操作:
ssh -t ec2-user@$host -i $keypath \
'sudo -iu some-user bash -c "mkdir -p /tmp/test/; cd /tmp/test ;
echo THIS_IS_TEST;
c(){ clear; }
touch test-txt;
c"'
现在这仍然没有意义,因为clear
在这种情况下没有意义,我删除了bash -l
因为这意味着你不能做任何事情。我认为你可能应该问一个新问题并解释这里的最终目标是什么。无论您需要做什么,这些都不太可能是最好的方法,因此,如果您提出新问题并向我们提供详细信息,我们应该能够提供更好的方法。
答案3
我认为你需要启用作业控制
#! /bin/bash
set -m
它们应该默认启用,但不知何故没有启用,我真的不知道为什么。