使用.bashrc而不破坏sftp


20

我的问题是,我每次登录ssh shell时都需要设置一些变量,并输出几行,与此同时,我必须能够使用sf​​tp通过Filezilla来压缩文件。

现在,按照http://www.openssh.org/faq.html上的openssh常见问题解答,如果您的启动脚本回显了任何类型的输出,则它将与sftp混淆。因此,它要么无限期地延迟,要么因“服务器关闭退出连接,退出代码为128”而出错。

我尝试过将.bashrc移至.bash_profile或在.bashrc中使用以下代码的解决方案:

if [ "$TERM" != "dumb" ]
then
   source .bashc_real
fi

和:

if [ "$TERM" = "xterm" ]
then
   source .bashc_real
fi

但是,没有任何效果。我的shell终端是bash,我使用filezilla连接到sftp。

Answers:


23

尝试这样做

if [ "$SSH_TTY" ]
then
   source .bashc_real
fi

17

迈克的答案可能会起作用。但是值得指出的是,您可以仔细选择要放入详细内容的启动文件来完成此操作。从bash手册页:

当bash作为交互式登录shell或具有--login选项的非交互式shell被调用时,它首先从文件/ etc / profile中读取并执行命令(如果该文件存在)。读取该文件后,它将按该顺序查找〜/ .bash_profile,〜/ .bash_login和〜/ .profile,并从存在且可读的第一个命令中读取并执行命令。启动外壳程序时,可以使用--noprofile选项禁止此行为。

启动不是登录外壳程序的交互式外壳程序时,如果该文件存在,则bash从〜/ .bashrc读取并执行命令。使用--norc选项可以禁止这种情况。--rcfile file选项将强制bash从文件而不是〜/ .bashrc中读取并执行命令。

sftp / scp工具启动了一个交互式非登录外壳程序,因此将以.bashrc为源。许多发行版都从.bash_profile提取.bashrc,反之亦然,因此可能会引起混淆。测试登录环境整洁度的一个好技巧是使用命令ssh进行插入,该命令模拟了scp / sftp连接的相同方式。例如:ssh myhost /bin/true将向您确切显示scp / sftp在连接时看到的内容。

一个简单的演示:

insyte@mazer:~$ echo "echo Hello from .profile" > .profile
insyte@mazer:~$ echo "echo Hello from .bashrc" > .bashrc

sazerac:~ insyte$ ssh mazer /bin/true
Hello from .bashrc
sazerac:~ insyte$

insyte@mazer:~$ rm .bashrc

sazerac:~ insyte$ ssh mazer /bin/true
sazerac:~ insyte$

第一次测试将导致scp / sftp / rsync等损坏。第二个版本可以正常工作。


我不同意“ sftp / scp工具启动交互式非登录外壳”,因为我们无法真正与该外壳进行交互。但是我不明白为什么.bashrc要采购scp或采购ssh host command
pynexj

2
术语“互动”不是主观的。这是bash用来描述其启动模式之一的术语。事实是sftp / scp启动了“交互式非登录外壳”。在这种情况下,可以与开发人员自由讨论是否应该采购.bashrc;我只是告诉你它的作用。
Insyte 2013年

2
Bashscpssh host command确实是非交互调用的。我只是在bash手册中发现了这一点:“ Bash尝试确定何时将其标准输入连接到网络连接上运行,就像由远程Shell守护程序(通常为rshd或安全Shell守护程序sshd)执行时一样。如果bash确定它以这种方式运行~/.bashrc,如果该文件存在并且可读,它将从中读取并执行命令 。” 这是有趣的历史
pynexj

1
另见远程登录非交互式非炮弹此wiki页面
pynexj

3

如果您使用的是csh:

if ($?prompt)
  ... interactive stuff ...

并且如果它是重击:

if [[ $- == *i* ]]; then
  ... interactive stuff ...
fi

或者使用bash正则表达式:

if [[ $- =~ i ]]; then
  ... interactive stuff ...
fi

这些行应在输出/回送某些内容的行之前。


嗨,请您解释一下代码。我知道$?是上一条命令的返回级别。我不明白$?提示和$-。还是csh特定?
乔尔·马修

1
@Droidzone:$?varcsh返回1,如果var被定义,否则为0。$-bash将有i它的价值,如果焦炭shell是交互的。
pynexj

应该更新答案来解释$-是shell选项的特殊变量。参见stackoverflow.com/questions/5163144/…–
maninvan

1

Mike的解决方案也对我有用。但是由于我的默认外壳是TCSH,因此我必须对修复进行如下修改(在.tcshrc中):

if ( $?SSH_TTY ) then
    exec /bin/bash
endif

只是想我会为大家的利益分享。


0

我更喜欢这里提到的其他一些解决方案,但是我认为我抛出了当前在bash和csh VM上使用的解决方案,以防止由于启动脚本中的echo命令而导致SFTP断开连接,以防万一有人发现信息有用。

在BASH中:

if [ $TERM == "xterm" ] || [ $TERM == "xterm-256color" ]; then
  echo "Xterm display identified: echo enabled"
  echo_disable="0"
else
  echo_disable="1"
fi

# Use the following for all subsequent echo commands
if [ $echo_disable == 0 ]; then
 echo "Safe to display on Xterm"
fi

在csh中:

if ($TERM == "xterm") then
  echo "Xterm display identified: echo enabled"
  set echo_disable = "0"
else
  set echo_disable = "1"
endif

# Use the following for all subsequent echo commands
if !( "$echo_disable" ) echo "Safe to display on Xterm"

这有点蛮力,但确实有效。


我尝试使用上面的[“ $ SSH_TTY”]代码,发现它仅适用于像腻子这样的简单客户端程序。当我使用NoMachine时,它不提供任何输出。这就是为什么我需要在上面的代码中包括“ xterm-256color”。
Bob Noonan

有趣的是,使用“ if($?SSH_TTY)then”也不适用于我的csh VM。我检查了,没有定义SSH_TTY环境变量。因此,我上面的代码可能会对其他情况类似的人有所帮助。
Bob Noonan

0

这是我的(默认).bashrc文件的第一行:

# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

交互式会话的检查可避免弄乱SCP,SFTP或ssh remote-host command模式。

没有这个,如果您的文件在stdout上.bashrc使用echo了打印或其他一些东西,您可能会遇到以下错误:

  • SFTP: Received message too long 168435779
  • SCP: protocol error: unexpected <newline>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.