我经常连接到学校的 Linux 实验室,远程完成编程作业。有时,当有很多其他学生登录到服务器时,连接速度会很慢,并且我会在连接超时期间丢失工作。实验室中有几台服务器可供选择,我希望能够在连接who
建立后立即自动运行,这样我就可以查看服务器的拥挤程度,如果服务器已经满了,就使用另一台。现在,我使用 .bash_aliases 文件中的函数来简化连接和密码输入:
在文件中~/.bash_aliases
:
#!/bin/bash
# ssh to the Linux lab. Takes hostnames defined in ~/.ssh/config as
# parameters
function sshll()
{
if [ "$@" ]
echo "Connecting to hostname $@";
sshpass -f <password_file> ssh $@;
else
echo "Connecting to default host";
sshpass -f <password_file> ssh <user@ipaddress>;
fi
}
这有效,所以我who
在命令末尾添加了ssh
:
在文件中~/.bash_aliases
:
#!/bin/bash
# ssh to the linux lab. Takes hostnames defined in ~/.ssh/config as
# parameters
function sshll()
{
if [ "$@" ]
echo "Connecting to hostname $@";
sshpass -f <password_file> ssh $@ 'who';
else
echo "Connecting to default host";
sshpass -f <password_file> ssh <user@ipaddress> 'who';
fi
}
这将连接、自动输入我的密码并运行who
,但随后关闭连接。有没有一种方法可以让我who
自动运行,而无需随后关闭连接?
答案1
总结:int_ua 的答案是正确的,最简单,最轻松。
为什么会有这样的效果
这又回到了任何 shell 的基本行为。当您登录时,您会得到 shell 的交互式版本。当您运行时,您基本上会得到。第一个允许您在获取点文件的同时运行您输入的任何内容,而第二个只执行这些命令并退出。本质上,没有办法在交互式使用之前运行命令(除非它在其中一个点文件中)或从单次命令(或任何 shell,不一定)获取交互式 shell。ssh [email protected]
ssh [email protected] -t "command1;command2"
/bin/sh -c 'command1;command2'
stdin
sh -c
sh
失败或不完整的想法
我的第一个想法是:如果 shell 使用服务器的本地.bashrc
,是否可以让它使用服务器上客户端的本地文件?嗯,不除非你将点文件复制到远程服务器使用 scp 或 rsync。
我的第二个想法是PROMPT_COMMAND
。这个非常好的bash
变量每次在显示PS1
提示之前都会运行命令,那么为什么不在 spawining 之前设置这个变量bash
,以便PROMPT_COMMAND="who; unset PROMPT_COMMAND"
我们将其作为单次运行?
问题是这个变量必须导出到远程服务器,并且吉尔斯回答帮助我做了这样的事情:
ssh -o SendEnv=PS1 ssh localhost -t bash
或者
ssh localhost -t " PROMPT_COMMAND='who; unset PROMPT_COMMAND' bash "
问题 ? -o 选项 SendEnv 必须允许您尝试发送的特定变量/etc/ssh/sshd_config
,此外,无论哪种情况,您仍然可以使用/bin/sh -c
对 int_ua 的答案略有改进
所以现在我们可以看到该ssh user@server -t 'command1;shell'
模式效果最好。除了一个小问题:/bin/sh -c
进程仍然存在,那么为什么不运行bash
以exec
替换该进程呢?
ssh [email protected] -t 'who;exec bash'
答案2
只需执行bash
就足够了:
sshpass -f <password_file> ssh <user@ipaddress> 'who; bash';
答案3
这是一个答案是,但绝对不是这回答。
我发现sshd
(远程主机上的 ssh 服务守护进程)在连接时会运行 ~/.ssh/rc 中的命令。我刚刚创建了这个文件,并添加到who
那里,现在每次我进行远程连接时都会显示一个用户列表,而且我仍然会获得登录 shell。
在远程主机上:
File ~/.ssh/rc:
#!/bin/bash
# This file is executed by sshd when a remote connection is started over ssh
who
在客户端:
In file ~/.bash_aliases:
#!/bin/bash
# ssh to the linux lab. Takes hostnames defined in ~/.ssh/config as
# parameters
function sshll()
{
if [ "$@" ]
echo "Connecting to hostname $@";
sshpass -f <password_file> ssh $@;
else
echo "Connecting to default host";
sshpass -f <password_file> ssh <user@ipaddress>;
fi
}
但是,我仍然有兴趣了解如何从客户端执行此操作,但是对于遇到类似问题的其他用户,由于缺乏权限或其他原因而无法使用 ~/.ssh/rc。
答案4
我知道这是一个老问题,但我想知道为什么没有人提到expect
,这似乎只是为这种情况设计的。(当然,您需要expect
先安装该软件包)。
!#/usr/bin/expect
spawn ssh user@host
expect "assword:"
send "mypassword\r"
expect "$ "
send "who\r"
interact