I cannot copy a file over scp when the remote machine .bashrc file includes source command to update paths and some variables. Why does it happen?
2 Answers
You should make part or all of your .bashrc
not run when your shell is non-interactive. (An scp
is an example of a non-interactive shell invocation, unless someone has radically altered your systems.) Then put all commands that can possibly generate output in that section of the file.
A standard way to do this in an init file is:
# Put all the commands here that should run regardless of whether
# this is an interactive or non-interactive shell.
Example command:
umask 0027
test if the prompt var is not set and also to prevent failures
when $PS1
is unset and set -u
is used
if [ -z "${PS1:-}" ]; then
# prompt var is not set, so this is not an interactive shell
return
fi
If we reach this line of code, then the prompt var is set, so
this is an interactive shell.
Put all the commands here that should run only if this is an
interactive shell.
Example command:
echo "Welcome, ${USER}. This is the ~/.bashrc file."
You might also see people use
[ -z "${PS1:-}" ] && return
instead of my more verbose if
statement.
If you don't want to rearrange your whole file, you can also just make certain lines run only in interactive context by wrapping them like so:
if [ -n "${PS1:-}" ]; then
echo "This line only runs in interactive mode."
fi
If you segregate your .bashrc
this way, then your scp
commands should no longer have this problem.

- 27
- 5

- 2,642
-
2Good advice. This problem has been around for over 30 years, dating from BSD's
rcp
command coupled withcsh
and.cshrc
. Hopefully, in time,ssh
can provide an alternative way of doingscp
that isn't affected by the remote user's shell at all. – Mark Plotnick Sep 08 '14 at 17:58 -
-
I had this issue; but needed to return (versus exit). When I used exit the scp didn't output; but also didn't copy files. – Raymond Kroeker Aug 16 '15 at 18:14
-
Your solution did not work for me (specifically in the case of resuming gnu screen), but this did: https://www.commandlinefu.com/commands/view/13589/makes-screen-your-default-shell-without-breaking-scp-or-sftp [ "$TERM" != "dumb" ] && [ -z "$STY" ] && screen -DRA – fbas Jan 28 '20 at 14:16
-
This explains what the problem is and how to fix it, but I'd love to know why it fails. What about putting an interactive command (e.g.
source
orecho
) in a~/.bashrc
file causes SCP to fail? – jvriesem Mar 30 '20 at 18:59 -
another way to check if shell interactive
[[ $- = *i* ]] || return
– Nahuel Fouilleul Feb 16 '21 at 14:10 -
1@jvriesem
source
does not harm, but output does. The problem simply seems to be thatscp
sends not only data but also commands over the standard streams. So putting anecho "hello"
in your .bashrc will result inhelloC0774 123 foo.txt
being transmitted, as scp sends the access pattern and size with theC
command first if you want to transfer the filefoo.txt
. But with the leading "hello" this is no longer understandable by the receiving client. – ThomasH Feb 03 '22 at 08:59
This solution worked for me as well. But since my default shell is TCSH, I had to slightly edit the fix as follows (in .tcshrc):
if ( $?SSH_TTY ) then
exec /bin/bash
endif
Just thought I would share for everyone's benefit.
/bin/sh
? Are you sourcing~/.bashrc
from~/.profile
? – jordanm Sep 08 '14 at 15:05scp
, which actually runsssh
to run a slightly differentscp
command on the remote system and then parses its output. If you can rewrite your .bashrc so that nothing it runs or sources will produce output,scp
will probably work. – Mark Plotnick Sep 08 '14 at 16:49