Sử dụng .bashrc mà không phá vỡ sftp


20

Vấn đề của tôi là tôi cần đặt một vài biến và xuất ra một vài dòng mỗi khi tôi đăng nhập vào ssh shell, đồng thời tôi phải có thể sử dụng sftp để làm mờ các tệp thông qua Filezilla.

Bây giờ, theo Câu hỏi thường gặp mở tại http://www.openssh.org/faq.html , nếu tập lệnh khởi động của bạn lặp lại bất kỳ loại đầu ra nào, nó sẽ gây rối với sftp. Vì vậy, nó sẽ trì hoãn vô thời hạn hoặc lỗi với "Kết nối được đóng bởi máy chủ với mã thoát 128".

Tôi đã thử các giải pháp như di chuyển .bashrc sang .bash_profile hoặc sử dụng đoạn mã sau trong .bashrc:

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

Và:

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

Tuy nhiên, không có gì hoạt động. Thiết bị đầu cuối shell của tôi là bash và tôi kết nối với sftp với filezilla.

Câu trả lời:


23

Thay vào đó hãy thử làm điều này

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

17

Câu trả lời của Mike có thể sẽ hoạt động. Nhưng thật đáng để chỉ ra rằng bạn có thể thực hiện việc này một cách cẩn thận khi chọn các tệp khởi động để đặt nội dung dài dòng vào. Từ trang bash man:

Khi bash được gọi dưới dạng shell đăng nhập tương tác hoặc dưới dạng shell không tương tác với tùy chọn --login, trước tiên, nó sẽ đọc và thực thi các lệnh từ tệp / etc / profile, nếu tệp đó tồn tại. Sau khi đọc tệp đó, nó tìm ~ / .bash_profile, ~ / .bash_login và ~ / .profile, theo thứ tự đó, đọc và thực thi các lệnh từ lệnh đầu tiên tồn tại và có thể đọc được. Tùy chọn --noprofile có thể được sử dụng khi trình bao bắt đầu ngăn chặn hành vi này.

Khi một vỏ tương tác không phải là vỏ đăng nhập được khởi động, bash sẽ đọc và thực thi các lệnh từ ~ / .bashrc, nếu tệp đó tồn tại. Điều này có thể bị ức chế bằng cách sử dụng tùy chọn --norc. Tùy chọn tệp --rcfile sẽ buộc bash đọc và thực thi các lệnh từ tệp thay vì ~ / .bashrc.

Các công cụ sftp / scp bắt đầu một vỏ không đăng nhập tương tác, vì vậy .bashrc sẽ có nguồn gốc. Nhiều bản phân phối nguồn .bashrc từ .bash_profile hoặc ngược lại, vì vậy nó có thể gây nhầm lẫn. Một mẹo hay để kiểm tra sự sạch sẽ của môi trường đăng nhập của bạn là ssh in bằng một lệnh, mô phỏng giống như cách kết nối scp / sftp. Ví dụ: ssh myhost /bin/truesẽ cho bạn thấy chính xác những gì scp / sftp nhìn thấy khi chúng kết nối.

Một bản demo đơn giản:

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$

Thử nghiệm đầu tiên sẽ khiến scp / sftp / rsync, v.v. Phiên bản thứ hai sẽ hoạt động tốt.


Tôi không đồng ý rằng "Các công cụ sftp / scp bắt đầu một lớp vỏ không đăng nhập tương tác " vì chúng ta không thể thực sự tương tác với trình bao. Nhưng tôi không hiểu tại sao .bashrcsẽ được source'd cho scphay ssh host command.
pynexj

2
Thuật ngữ "tương tác" không chủ quan. Đây là một thuật ngữ được sử dụng bởi bash để mô tả một trong các chế độ khởi động của nó. Có một thực tế là sftp / scp bắt đầu một "vỏ không đăng nhập tương tác". Vui lòng tranh luận với các nhà phát triển về việc không tìm nguồn cung ứng .bashrc có phù hợp trong trường hợp này hay không; Tôi chỉ nói với bạn những gì nó làm.
Insyte 26/03/13

2
Bashđược gọi bởi scphoặc ssh host commandthực sự là không tương tác . Tôi chỉ tìm thấy điều này trong hướng dẫn sử dụng bash: "Bash cố gắng xác định khi nào nó đang được chạy với đầu vào tiêu chuẩn được kết nối với kết nối mạng , như khi được thực hiện bởi trình nền shell từ xa, thường là rshd hoặc trình nền daemon an toàn sshd . Nếu bash xác định nó đang được chạy theo kiểu này, nó đọc và thực thi các lệnh từ ~/.bashrc, nếu tập tin đó tồn tại và có thể đọc được. " Đây là lịch sử thú vị .
pynexj

1
Cũng xem phần Remote không đăng nhập shell không tương tác trong trang wiki này .
pynexj

3

Nếu bạn đang sử dụng csh:

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

Và nếu đó là bash:

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

hoặc thay thế bằng cách sử dụng biểu thức bash thông thường:

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

Những dòng này nên đi trước các dòng mà bạn bỏ qua / lặp lại một cái gì đó.


Xin chào, bạn có thể giải thích mã, xin vui lòng. Tôi biết $ đó? là mức trả về của lệnh trước đó. Tôi không hiểu $? Nhắc và $ -, mặc dù. Hay là csh cụ thể?
Joel G Mathew

1
@Droidzone: $?vartrong cshlợi nhuận 1 nếu varđược định nghĩa và 0 nếu ngược lại. $-trong bashsẽ có ichar trong giá trị của nó nếu shell tương tác.
pynexj

Nên cập nhật câu trả lời để giải thích $ - là một biến đặc biệt của các tùy chọn shell. xem stackoverflow.com/questions/5163144/ từ
maninvan

1

Giải pháp của Mike cũng làm việc cho tôi. Nhưng vì shell mặc định của tôi là TCSH, tôi đã phải chỉnh sửa một chút bản sửa lỗi như sau (trong .tcshrc):

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

Chỉ cần nghĩ rằng tôi sẽ chia sẻ vì lợi ích của mọi người.


0

Tôi thích một số giải pháp khác được đề cập ở đây tốt hơn, nhưng tôi nghĩ rằng tôi đã loại bỏ giải pháp mà tôi hiện đang sử dụng trên máy bash và csh VM của mình để ngăn chặn ngắt kết nối SFTP do lệnh echo trong tập lệnh khởi động của tôi, trong trường hợp bất kỳ ai thấy thông tin hữu ích .

Trong 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

Trong 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"

Đó là một chút vũ phu, nhưng nó hoạt động.


Tôi đã thử sử dụng mã ["$ SSH_TTY"] ở trên và thấy rằng nó chỉ hoạt động cho các chương trình máy khách đơn giản như putty. Khi tôi sử dụng NoMachine, nó không cung cấp bất kỳ đầu ra nào. Đây là lý do tại sao tôi cần đưa "xterm-256color" vào đoạn mã trên.
Bob Noonan

Thật thú vị, sử dụng "if ($? SSH_TTY)" cũng không hoạt động với máy ảo csh của tôi. Tôi đã kiểm tra và không có biến môi trường SSH_TTY được xác định. Vì vậy, mã của tôi ở trên có thể hữu ích cho những người khác có tình huống tương tự.
Bob Noonan

0

Dưới đây là những dòng đầu tiên của .bashrctệp (mặc định) của tôi :

# ~/.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

Việc kiểm tra phiên tương tác sẽ tránh gây rối với SCP, SFTP hoặc ssh remote-host command chế độ.

Nếu không có điều này, nếu tệp của bạn .bashrcsử dụng echohoặc một số nội dung khác in trên thiết bị xuất chuẩn, bạn có thể gặp phải loại lỗi này:

  • SFTP: Received message too long 168435779
  • SCP: protocol error: unexpected <newline>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.