SCP không hoạt động khi echo trong .bashrc?


81

Tôi có hai người dùng trong Fedora:

  1. Wani
  2. root (khá rõ ràng!)

Nội dung .bashrc của người dùng Wani của tôi là:

# .bashrc
echo "Hello"
# Source global definitions
if [ -f /etc/bashrc ]; then
    . /etc/bashrc
fi

# User specific aliases and functions

Bây giờ sau khi đăng nhập vào root, tôi gõ các lệnh sau:

[root@Dell Wani]# touch try.txt
[root@Dell Wani]# service sshd start
[root@Dell Wani]# scp try.txt Wani@localhost:~/
Wani@localhost's password: 
Hello
[root@Dell Wani]# 

Bây giờ tôi đăng nhập vào Wani và gõ:

[Wani@Dell ~]$ cat try.txt
cat: try.txt: No such file or directory
[Wani@Dell ~]$ 

Bây giờ tôi lại đăng nhập vào root và gõ lệnh tương tự với -v:

[root@Dell Wani]# scp -v morph.log Wani@localhost:
Executing: program /usr/bin/ssh host localhost, user Wani, command scp -v -t -- .
OpenSSH_5.6p1, OpenSSL 1.0.0j-fips 10 May 2012
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Applying options for *
debug1: Connecting to localhost [127.0.0.1] port 22.
debug1: Connection established.
debug1: permanently_set_uid: 0/0
debug1: identity file /root/.ssh/id_rsa type -1
debug1: identity file /root/.ssh/id_rsa-cert type -1
debug1: identity file /root/.ssh/id_dsa type -1
debug1: identity file /root/.ssh/id_dsa-cert type -1
debug1: Remote protocol version 2.0, remote software version OpenSSH_5.6
debug1: match: OpenSSH_5.6 pat OpenSSH*
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_5.6
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-ctr hmac-md5 none
debug1: kex: client->server aes128-ctr hmac-md5 none
debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP
debug1: SSH2_MSG_KEX_DH_GEX_INIT sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY
debug1: Host 'localhost' is known and matches the RSA host key.
debug1: Found key in /root/.ssh/known_hosts:2
debug1: ssh_rsa_verify: signature correct
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: Roaming not allowed by server
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-     with-mic,password
debug1: Next authentication method: gssapi-keyex
debug1: No valid Key exchange context
debug1: Next authentication method: gssapi-with-mic
debug1: Unspecified GSS failure.  Minor code may provide more information
Credentials cache file '/tmp/krb5cc_0' not found

debug1: Unspecified GSS failure.  Minor code may provide more information
Credentials cache file '/tmp/krb5cc_0' not found

debug1: Unspecified GSS failure.  Minor code may provide more information


debug1: Unspecified GSS failure.  Minor code may provide more information


debug1: Next authentication method: publickey
debug1: Trying private key: /root/.ssh/id_rsa
debug1: Trying private key: /root/.ssh/id_dsa
debug1: Next authentication method: password
Wani@localhost's password: 
debug1: Authentication succeeded (password).
Authenticated to localhost ([127.0.0.1]:22).
debug1: channel 0: new [client-session]
debug1: Requesting no-more-sessions@openssh.com
debug1: Entering interactive session.
debug1: Sending environment.
debug1: Sending env XMODIFIERS = @im=none
debug1: Sending env LANG = en_US.UTF-8
debug1: Sending command: scp -v -t -- .
Hello
[root@Dell Wani]# debug1: client_input_channel_req: channel 0 rtype exit-status      reply      0
debug1: channel 0: free: client-session, nchannels 1
debug1: fd 0 clearing O_NONBLOCK
debug1: fd 1 clearing O_NONBLOCK
Transferred: sent 1664, received 1976 bytes, in 0.1 seconds
Bytes per second: sent 22961.5, received 27266.8
debug1: Exit status 0

(Và sau khi tôi nhấn Enter)

[root@Dell Wani]# 

Bất cứ ai có thể vui lòng làm sáng tỏ những gì chính xác đã xảy ra ở đây? Tại sao tệp không được sao chép vào Wani từ gốc?


Về cpthì sao? Không cp try.txt ~Wani/hoạt động?
nneonneo

Thực sự có thể là các lệnh tương tác hoặc đầu ra giả từ của bạn .bashrccó thể làm hỏng một số tình huống không tương tác . Hãy thử tạo mã có điều kiện cho case $- in *i*hoặc một số mã như vậy.
ba

@nneonneo: Điều đó hoạt động. Trên thực tế, ngay cả khi tôi có hai người dùng trên các máy tính khác nhau, tệp không được sao chép!
Nehal J Wani

1
Tất cả các bài viết tôi đã xem đều mô tả TẠI SAO vấn đề này tồn tại trong các tệp bashrc khác nhau, v.v. Tuy nhiên, khi SCP / STFP vào một máy bạn KHÔNG SỞ HỮU và KHÔNG THỂ thay đổi các tập lệnh khởi động, giải pháp sau đó là gì ???
ChuckB

Cuối cùng tôi đã chuyển hướng tất cả các tiếng vọng sang stderr. Hoạt động, nhưng ...
Andreas

Câu trả lời:


78

Sử dụng echotrong một thời .bashrcgian sẽ bị phá vỡ scp, như scpmong đợi để xem dữ liệu giao thức của nó qua các kênh stdin / stdout. Xem https://bugzilla.redhat.com/show_bug.cgi?id=20527 để thảo luận thêm về vấn đề này.

Có một số giải pháp thay thế có sẵn:

  • Điều kiện trên cờ 'tương tác' (ví dụ case $- in *i*như được đề xuất bởi tripleee)
  • Sử dụng ttytiện ích để phát hiện một trình bao tương tác (ví dụ: if tty > /dev/nullhoặc if [ -t 0 ])
  • Kiểm tra giá trị của $SSH_TTY

Tôi cho rằng bạn nên sử dụng cái nào phù hợp với bạn. Rất tiếc, tôi không biết lựa chọn tốt nhất (di động nhất / đáng tin cậy nhất) là gì.


6
Chỉ để làm rõ lệnh "trường hợp" sẽ là:case $- in *i*) echo This is safe since the shell is interactive; esac
mlathe

shoptcũng là một lựa chọn thay thế
vesperto 23/03/18

1
Vì máy chủ của tôi luôn được truy cập qua SSH nên SSH_TTY luôn được đặt. Sử dụng -t 0điều kiện làm việc tốt cho tôi. Tôi sử dụng hàm sau trên toàn bộ bashrc của tôi bây giờ. safe_echo() { if [[ -t 0 ]];then echo -e "$*" fi }
Sandip Bhattacharya

if [[ "$SSH_TTY" == */dev/pts/* ]] ; thenbên trong nếu đặt nội dung của bạn được in sang stdout, thì scp sẽ hoạt động tốt.
BeatingBytes

@BeatingBytes & @Sandip Bhattacharya, [[không phải là di động và tôi cũng không nghĩ nó là posix. Hãy thử điều này trong dashvỏ: if [[ 0 = 0 ]]; then echo x; else echo y; fi. Bạn nhận được dash: 3: [[: not found,.
Chế độ xem hình elip

19

Để thêm vào các tùy chọn của nneonneo, bạn cũng có thể điều kiện với cờ tương tác với

if [[ $- =~ "i" ]]

mà tôi nghĩ có thể là cách rõ ràng nhất trong bash.


[[không phải là di động và tôi cũng không nghĩ nó là posix. Hãy thử điều này trong dashvỏ: if [[ 0 = 0 ]]; then echo x; else echo y; fi. Bạn nhận được dash: 3: [[: not found,.
Chế độ xem hình elip


11

Các mặc định Ubuntu .bashrcchứa đoạn mã sau đó đã chăm sóc của vấn đề:

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

4
ngắn hơn:[[ $- != *i* ]] && return
phil294 14/12/18

2
Biểu mẫu được cung cấp trong câu trả lời của bạn tương thích với POSIX. Những gì bạn cung cấp trong nhận xét của mình không phải là POSIX vì việc sử dụng [[tính năng. Không quá khó đối với tệp bashrc;) nhưng bạn có thể muốn sử dụng nó trong ngữ cảnh / trình bao khác.
Totor

4

Trong .bashrc, sử dụng STDERR làm đầu ra thay thế:

echo "# Important Notice" >&2

Cập nhật: không sử dụng nó! Gần đây, chúng tôi đã gặp sự cố rằng một công cụ (nguồn đóng) không thành công do echoSTDERR trong .bashrc. Công cụ (đang sử dụng rcp) mong đợi không có đầu ra nào, cả trên STDOUT hay STDERR. Và nó bị mắc kẹt khi nhận được tiếng vang. Bài học rút ra: hãy tạo các tài khoản riêng biệt cho con người và cho máy móc (tập lệnh) hoặc chỉ dừng việc xử lý qua .bashrc.


"Tạo tài khoản riêng cho con người và cho máy móc" bị đánh giá thấp.
Andreas

1

Cách kiểm tra cơ động nhất cho một trình bao tương tác dường như là:

test -t 0
if [ $? -eq 0 ]
then
    # interactive
    ;
else
    # non-interactive
    ;
fi

0

giải pháp của nneonneo cũng hiệu quả với tôi. Nhưng vì trình bao 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ỉ nghĩ rằng tôi sẽ chia sẻ vì lợi ích của mọi người.


0

Nếu bạn đang sử dụng Red Hat Enterprise Linux (RHEL) hoặc biến thể, hãy thả tập lệnh thực hiện echohoặc bất cứ điều gì bạn muốn vào /etc/profile.d/


0

Nếu bạn cũng muốn câu lệnh echo, câu trả lời của @ Blauhirn, bạn có thể tiếp tục đặt / s câu lệnh echo của mình sau điều kiện trường hợp.

case $- in
    *i*) ;;
    *) return;;
esac

echo "Your Greeting/Warning Message/s here!"

-1
if [ 0 -eq $(shopt -q login_shell; echo $?) ]; then
  echo "do something?"
fi

Nguồn


Sẽ rất tốt nếu cung cấp một số bối cảnh cho OP.
aljabear

Bối cảnh và thông tin liên quan có thể được trích xuất từ ​​các câu trả lời khác và chính câu hỏi. Đây chỉ là một cách khác để thực hiện những gì đã được hiểu, với tỷ lệ tín hiệu trên nhiễu thấp.
vesperto
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.