SCP funktioniert nicht, wenn Echo in .bashrc?

80

Ich habe zwei Benutzer in Fedora:

  1. Wani
  2. root (ganz offensichtlich!)

Mein Inhalt von .bashrc des Benutzers Wani ist:

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

# User specific aliases and functions

Nachdem ich mich bei root angemeldet habe, gebe ich die folgenden Befehle ein:

[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]# 

Jetzt logge ich mich bei Wani ein und tippe:

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

Jetzt logge ich mich wieder bei root ein und tippe den gleichen Befehl mit -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 [email protected]
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

(Und nachdem ich die Eingabetaste gedrückt habe)

[root@Dell Wani]# 

Kann jemand bitte etwas Licht ins Dunkel bringen, was genau hier passiert ist? Warum wurde die Datei nicht von root nach Wani kopiert?

Nehal J Wani
quelle
Was ist mit cp? Funktioniert cp try.txt ~Wani/?
Nneonneo
Es ist in der Tat möglich, dass interaktive Befehle oder falsche Ausgaben von Ihnen .bashrceinige nicht interaktive Szenarien ruinieren. Versuchen Sie, den Code von case $- in *i*oder einem ähnlichen Zustand abhängig zu machen .
Tripleee
@nneonneo: Das funktioniert. Selbst wenn ich die beiden Benutzer auf verschiedenen Computern habe, wird die Datei nicht kopiert!
Nehal J Wani
1
Alle Beiträge, die ich gesehen habe, beschreiben, WARUM dieses Problem in verschiedenen bashrc-Dateien usw. besteht. Wenn Sie jedoch SCP / STFP auf einen Computer übertragen, können Sie die Startskripte NICHT besitzen und NICHT ändern. Was ist dann die Lösung?
ChuckB
Am Ende habe ich alle Echos an stderr umgeleitet. Funktioniert, aber ...
Andreas

Antworten:

76

Die Verwendung echoin a .bashrcwird unterbrochen scp, da scperwartet wird, dass die Protokolldaten über die stdin / stdout-Kanäle angezeigt werden. Weitere Informationen zu diesem Thema finden Sie unter https://bugzilla.redhat.com/show_bug.cgi?id=20527 .

Es stehen einige Problemumgehungen zur Verfügung:

  • Bedingung auf der 'interaktiven' Flagge (z. B. case $- in *i*wie vom Tripleee vorgeschlagen)
  • Verwenden Sie das ttyDienstprogramm, um eine interaktive Shell zu erkennen (z. B. if tty > /dev/nulloder if [ -t 0 ])
  • Überprüfen Sie den Wert von $SSH_TTY

Ich nehme an, Sie sollten das verwenden, was für Sie funktioniert. Ich weiß leider nicht, was die beste (tragbarste / zuverlässigste) Option ist.

nneonneo
quelle
6
Nur um den "Fall" Befehl zu klären, wäre:case $- in *i*) echo This is safe since the shell is interactive; esac
mlathe
shoptist auch eine Alternative
Vesperto
1
Da auf meinen Host immer über SSH zugegriffen wird, ist SSH_TTY immer festgelegt. Die -t 0Bedingung zu verwenden hat bei mir gut funktioniert. Ich benutze jetzt die folgende Funktion in meinem gesamten Bashrc. safe_echo() { if [[ -t 0 ]];then echo -e "$*" fi }
Sandip Bhattacharya
if [[ "$SSH_TTY" == */dev/pts/* ]] ; thenWenn Sie Ihren Inhalt, der gedruckt wird, auf stdout setzen, funktioniert scp einwandfrei.
BeatingBytes
@BeatingBytes & @Sandip Bhattacharya, [[ist nicht portabel und ich denke auch nicht, dass es posix ist. Versuchen Sie dies in der dashShell : if [[ 0 = 0 ]]; then echo x; else echo y; fi. Sie bekommen , dash: 3: [[: not found.
Elliptische Ansicht
19

Um die Optionen von nneonneo zu erweitern, können Sie auch mit dem interaktiven Flag mit konditionieren

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

was ich denke, ist möglicherweise der klarste Weg in Bash.

Drew Ogle
quelle
[[ist nicht tragbar und ich denke auch nicht, dass es posix ist. Versuchen Sie dies in der dashShell : if [[ 0 = 0 ]]; then echo x; else echo y; fi. Sie bekommen , dash: 3: [[: not found.
Elliptische Ansicht
10

Das Standard- Ubuntu .bashrcenthält das folgende Snippet, das das Problem bereits behebt:

# If not running interactively, don't do anything
case $- in
    *i*) ;;
    *) return;;
esac
phil294
quelle
4
kürzer:[[ $- != *i* ]] && return
phil294
2
Das in Ihrer Antwort angegebene Formular ist POSIX-kompatibel. Was Sie in Ihrem Kommentar anbieten, ist aufgrund der Verwendung der [[Funktion nicht POSIX . Nicht so problematisch für eine bashrc-Datei;), aber Sie möchten sie möglicherweise in einem anderen Kontext / einer anderen Shell verwenden können.
Totor
4

In der .bashrcVerwendung STDERR als Ausgabe statt:

echo "# Important Notice" >&2

Update: nicht benutzen! Wir hatten kürzlich ein Problem, dass ein (Closed Source) Tool aufgrund eines echoSTDERR in fehlgeschlagen ist .bashrc. Das Tool (using rcp) erwartete überhaupt keine Ausgabe, weder bei STDOUT noch bei STDERR. Und es blieb hängen, als es das Echo bekam. Lektion gelernt: Erstellen Sie separate Konten für Menschen und Maschinen (Skripte) oder hören Sie einfach auf, über zu tatteln .bashrc.

bal
quelle
"Separate Konten für Menschen und Maschinen erstellen" wird unterschätzt.
Andreas
1

Die portabelste Methode zum Testen einer interaktiven Shell scheint zu sein:

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

Die Lösung von nneonneo hat auch bei mir funktioniert. Da meine Standard-Shell jedoch TCSH ist, musste ich den Fix wie folgt leicht bearbeiten (in .tcshrc):

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

Ich dachte nur, ich würde zum Nutzen aller teilen.

Vijay Padiyar
quelle
0

Wenn Sie mit Red Hat Enterprise Linux (RHEL) oder einer Variante arbeiten, legen Sie ein Skript, das das echooder was auch immer Sie wollen, in /etc/profile.d/ ab.

Everett Toews
quelle
0

Wenn Sie auch Echoanweisungen wünschen, die Antwort von @ Blauhirn, können Sie Ihre Echoanweisungen weiterhin nach der Fallbedingung platzieren.

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

echo "Your Greeting/Warning Message/s here!"
Kishan Sangani
quelle
-1
if [ 0 -eq $(shopt -q login_shell; echo $?) ]; then
  echo "do something?"
fi

Quelle

vesperto
quelle
Es wäre schön, einen Kontext für das OP bereitzustellen.
Aljabear
Kontext und relevante Informationen können bereits aus anderen Antworten und der Frage selbst extrahiert werden. Dies ist nur eine weitere Möglichkeit, das bereits Verstandte mit einem niedrigen Signal-Rausch-Verhältnis zu tun.
Vesperto