关于bash:我如何直接ssh到特定目录?

How can I ssh directly to a particular directory?

我经常需要登录到几个服务器中的一个,然后转到那些机器上的几个目录中的一个。目前我做的事情是这样的:

1
2
3
4
5
6
localhost ~]$ ssh somehost

Welcome to somehost!

somehost ~]$ cd /some/directory/somewhere/named/Foo
somehost Foo]$

我有一些脚本可以确定我需要进入哪个主机和哪个目录,但我找不到一种方法:

1
2
3
4
5
localhost ~]$ go_to_dir Foo

Welcome to somehost!

somehost Foo]$

有没有一个简单,聪明或任何方法做到这一点?


您可以执行以下操作:

1
ssh -t xxx.xxx.xxx.xxx"cd /directory_wanted ; bash"

这样,您就可以在需要的目录上得到一个shell。

解释

-t Force pseudo-terminal allocation. This can be used to execute arbitrary screen-based programs on a remote machine, which can be very useful, e.g. when implementing menu services.

Multiple -t options force tty allocation, even if ssh has no local tty.

  • 如果不使用-t,则不会出现提示。
  • 如果不添加; bash,则连接将关闭,并将控制权返回到本地计算机。


你可以添加

1
cd /some/directory/somewhere/named/Foo

到另一个主机的.bashrc文件(或.profile或任何你称之为它的文件)。这样,无论您从何处登录服务器,无论您从何处登录,它都会为您提供正确的目录,您所要做的就是像正常一样使用ssh

关于诅咒,Rogeriopvl的解决方案也很有效,但是它有点冗长,而且你必须记住每次都这样做(除非你做了一个别名),所以它看起来不那么"有趣"。


我已经创建了一个工具,可以连续地将ssh和cd导入到服务器中,这个工具的名称很恰当。对于您给出的示例,您只需使用:

1
sshcd somehost:/some/directory/somewhere/named/Foo

如果您有任何问题,请告诉我!


基于对@rogeriopvl答案的补充,我建议如下:

1
ssh -t xxx.xxx.xxx.xxx"cd /directory_wanted && bash"

&&链接命令将使下一个命令仅在前一个命令成功时运行(而不是使用;,后者按顺序执行命令)。当需要对执行命令的目录执行cd时,这特别有用。

想象一下这样做:

1
/home/me$ cd /usr/share/teminal; rm -R *

目录teminal不存在,这会导致您留在主目录中,并使用以下命令删除其中的所有文件。

如果使用&&

1
/home/me$ cd /usr/share/teminal && rm -R *

在未找到目录后,该命令将失败。


我的首选方法是使用ssh配置文件(如下所述),但根据您的用途,有几种可能的解决方案。

命令行参数

我认为这种方法的最佳答案是Christianbundy对公认答案的答复:

1
ssh -t example.com"cd /foo/bar; exec \$SHELL -l"

使用双引号将允许您使用本地计算机中的变量,除非它们被转义(这里是$SHELL)。或者,您可以使用单引号,并且您使用的所有变量都将是来自目标机器的变量:

1
ssh -t example.com 'cd /foo/bar; exec $SHELL -l'

巴什函数

通过将命令包装在bash函数中,可以简化命令。假设您只想键入:

1
sshcd example.com /foo/bar

您可以通过将其添加到您的~/.bashrc中来实现这一点:

1
sshcd () { ssh -t"$1""cd "$2"; exec \$SHELL -l"; }

如果您使用的是远程计算机上存在的目录变量,请确保对其进行转义或用单引号括起来。例如,这将CD到存储在远程计算机上的JBOSS_HOME变量中的目录:

1
sshcd example.com \$JBOSS_HOME

SSH配置文件

如果您希望使用正常ssh命令的特定(或任何)主机一直看到这种行为,而不必使用额外的命令行参数,那么可以在ssh配置文件中设置RequestTTYRemoteCommand选项。

例如,我只想键入以下命令:

1
ssh qaapps18

但希望它始终像以下命令那样工作:

1
ssh -t qaapps18 'cd $JBOSS_HOME; exec $SHELL'

所以我把这个添加到我的~/.ssh/config文件中:

1
2
3
Host *apps*
    RequestTTY yes
    RemoteCommand cd $JBOSS_HOME; exec $SHELL

现在,该规则适用于主机名中包含"apps"的任何主机。

有关详细信息,请参阅http://man7.org/linux/man-pages/man5/ssh_config.5.html


在我非常具体的情况下,我只想在远程主机中执行一个命令,在Jenkins从机的特定目录中执行:

1
2
3
4
ssh myuser@mydomain
cd /home/myuser/somedir
./commandThatMustBeRunInside_somedir
exit

但是我的机器不能执行ssh(我想它不能分配一个伪tty),并让我给出以下错误:

1
Pseudo-terminal will not be allocated because stdin is not a terminal

我可以绕过这个问题,将"cd to dir+my command"作为ssh命令的参数传递(不必分配伪终端),并通过传递选项-t来明确地告诉ssh命令我不需要伪终端分配。

1
ssh -T myuser@mydomain"cd /home/myuser/somedir; ./commandThatMustBeRunInside_somedir"


我使用环境变量cdpath


登录后直接转到的另一种方法是创建"别名"。当您登录到您的系统时,只需键入该别名,您就可以进入该目录。

示例:alias=myfolder'/var/www/folder'

登录到系统类型后,该别名(在系统的任何部分都有效)如果不在bashrc中,这个命令将在当前会话中工作。所以您也可以将这个别名添加到bashrc中,以便将来使用它。

$myfolder=>带您进入该文件夹


-t的想法更进一步。我保留了一组调用下面的脚本,以转到我经常访问的主机中的特定位置。我把它们都放在~/bin里,把那个目录放在我的路径上。

1
2
3
4
5
6
7
8
9
10
#!/bin/bash

# does ssh session switching to particular directory
# $1, hostname from config file
# $2, directory to move to after login
# can save this as say 'con' then
# make another script calling this one, e.g.
# con myhost repos/i2c

ssh -t $1"cd $2; exec \$SHELL --login"

ssh本身提供了一种通信方式,它对目录一无所知。因为您可以指定要执行的远程命令(默认情况下,这是您的shell),所以我将从那里开始。


只需使用以下命令修改您的家:usermod -d /newhome username