We've intentionally built OpenSSH using this switch: --with-default-path blank. We're attempting to deploy OpenSSH so that the server does not include the scp binary.

Now when we try to do an scp from a local machine (client) to a remote machine (server) we're getting this message:

scp command not found

The server appears to expect the scp binaries to be present on both sides (client & server). So why do we need the scp binary on the remote end? Isn't it sufficient to only have it on the local machine (client)? Can anyone please clarify?

NOTE: If scp is not present on the remote server where we want to copy some file, it throws out an error like this on the remote (server):

scp command not found


I think you've answered your own question: you need scp on both sides.

The local instance of scp invokes scp remotely with the undocumented -t flag to handle the file transfer protocol.

If you really don't have scp, but you do have an ssh server, you might be able to use sftp to transfer the files, as in many cases the SFTP server component is built in to the ssh server.

  • so when remote scp also gets invoked, which scp actually copies the file contents from the source and write to the destination ..These are scp/ssh logs on client side..... The issue I am facing is " when I set default linux path on remote server to empty one, scp from outside to remote server doesnot work, as it needs default path of scp.. but scp from remote server to outside works..
    – user298537
    Jul 6 '18 at 14:10
  • "debug1: Sending command: scp -v -t /root debug2: channel 0: request exec confirm 1 debug2: callback done debug2: channel 0: open confirm rwindow 0 rmax 32768 debug2: channel 0: rcvd adjust 2097152 debug2: channel_input_status_confirm: type 99 id 0 debug2: exec request accepted on channel 0 Sending file modes: C0644 853 temp.sh debug2: channel 0: rcvd ext data 24 temp.sh 100% 853 0.8KB/s 00:00 debug2: channel 0: read<=0 rfd 4 len 0 debug2: channel 0: read failed "
    – user298537
    Jul 6 '18 at 14:20


The SSH protocol is facilitating multiple overlapping "services" of which file copying is one of them. The way the SSH protocol does this is by launching scp -t as a child process on a server, when a client connects to it using the scp command line tool.

Each server where SSH is installed requires a full compliment of CLI tools to provide all the "services" that are part of SSH (ssh, scp, sftp). There location on disk is only required by the managing sshd server daemon. This means they can be in any location, the clients are not aware nor need to be, they're only communicating with sshd via TCP port (typically 22) as client/server.


Applications such as scp and rsync and ssh itself are client/server applications. This means that they require both a client application scp and a server application. In this case, scp is both.

Here's an example

$ scp /Users/user1/thumbnails-digikam.db pi-hole:/tmp/.
thumbnails-digikam.db                                                                                                                                   0%    0     0.0KB/s   --:-- ETA^Z
[1]+  Stopped                 scp /Users/sammingolelli/thumbnails-digikam.db pi-hole:/tmp/.

I've started a scp from my laptop to my Raspberry Pi server (pi-hole), and then paused it mid-stream via Ctrl+Z.

If I then ssh to the Raspberry Pi server and do a ps:

$ ps -eaf | grep [s]cp
pi        9688  6147  0 11:11 ?        00:00:00 scp -t /tmp/.

We can see that the application server scp is running, and writing our file to /tmp directory. We can see the file in this paused state being written as well:

Rasberry Pi (server)
$ ls -l /tmp/thumbnails-digikam.db
-rw-r--r-- 1 pi pi 2260992 Jul  6 11:12 /tmp/thumbnails-digikam.db
laptop (client)
$ ls -l ~/thumbnails-digikam.db
-rw-r--r--  1 user1  staff  38551552 Jun  4 00:47 /Users/user1/thumbnails-digikam.db

If we let the scp continue by un-pausing it on the laptop (client):

$ fg
scp /Users/user1/thumbnails-digikam.db pi-hole:/tmp/.

It'll finish and if we look again on the Raspberry Pi (server) you'll see that the scp application is no longer running:

$ ps -eaf|grep [s]cp

OpenSSH is a bit unique in that it starts server applications (daemons) on demand just for the duration of a particular operation, and then once the transfer is complete, it terminates them.

The original daemon that's facilitating this is the ssh daemon:

$ ps auxf | less
root      6132  0.0  0.6  11524  5812 ?        Ss   02:53   0:00  \_ sshd: pi [priv]
pi        6147  0.0  0.4  11812  4016 ?        S    02:53   0:03      \_ sshd: pi@pts/0
pi        6150  0.0  0.4   6172  4036 pts/0    Ss   02:53   0:00          \_ -bash
root      6172  0.0  0.3   7232  3336 pts/0    S    02:53   0:00          |   \_ sudo -Es
root      6176  0.0  0.4   6120  4180 pts/0    S    02:53   0:00          |       \_ /bin/bash
root      9772  0.0  0.3   7888  3076 pts/0    R+   11:20   0:00          |           \_ ps auxf
root      9773  0.0  0.0   3800   480 pts/0    S+   11:20   0:00          |           \_ less
pi        9745  0.2  0.1   3988  1872 ?        Ss   11:19   0:00          \_ scp -t /tmp/.

Notice the parent/child hierarchy of scp, it's a child process of ssh.

Anatomy of a scp session

If you take a look at the OReilly SSH book there's a diagram that shows the mechanics of how scp connections work.


In the diagram above, you can see that when the scp <file> <server>:/<path> command is executed, it gets translated to something like this on the client side:

/usr/bin/ssh -x -oForwardAgent=no -oPermitLocalCommand=no -oClearAllForwardings=yes -- pi-hole scp -t /tmp/.

The client (scp) in this case is directing the sshd daemon on the client side to send a request to the server's sshd telling it to launch scp -t /tmp on the remote side.

Based on the documentation this is by design how scp uses SSH's tunnel.


Additional insights

I did some experiments where I made a copy of the scp binary to myscp and then ran this on the client. In every instance, the /usr/bin/ssh ... command still showed the -- someserver scp -t /tmp/..

This leads me to believe that the name of the scp executable, though referenced by the scp client when the ssh command is executed, does not get passed to the client directly. Rather the sshd daemon has the names for the various client tools that it supports, hardcoded within it.

This is further backed up by the details shown in the able above.


It's not possible to completely remove/disable the definition of --with-default-path when compiling sshd. Removing it completely, breaks sshd's ability to look for scp -t <dir> when an scp connection is triggered.

The best you can do to isolate sshd would be to designate a directory, which only contains the various binaries that make up OpenSSH.


  • okay I got this point.But my doubt is when I execute scp from client and I did "ps -eaf" on client side and i got this process "/usr/bin/ssh -x -l root -- <SERVER_IP_ADDR> scp -t /root".so is this internal command(triggered by normal scp from client) is same as executing this command" ssh root@<SERVER_IP_ADDR> scp temp_file root@<SERVER_IP_ADDR>:/root" manually on client .I want to understand how sshd interprets this scp (first as well as second case mentioned above) and how sshd executes scp command..In second case,if we dont allow commands to get executed on server(like scp) from remote end.
    – user298537
    Jul 16 '18 at 17:17
  • will that affect first case also ? so are both the cases same ? Please let me know if I am not clear
    – user298537
    Jul 16 '18 at 17:17
  • @priyap - I now see what you're truly asking about, let me think about it and respond in a bit: your asking about this on the client server when you run scp - /usr/bin/ssh -x -oForwardAgent=no -oPermitLocalCommand=no -oClearAllForwardings=yes -l root -- remotesrv.mydom.com scp -t /tmp/.
    – slm
    Jul 16 '18 at 17:48
  • 1
    Thanks a lot ..This info is really helpful..I am trying to understand sshd code (in server perspective) , (i.e.,) how sshd interprets the scp command recevied from client(scp -t bar) , whether its executing this scp command through system or exec or fork..Please let me know if you come across this flow in sshd.
    – user298537
    Jul 17 '18 at 7:10
  • 1
    After authentication is succeeded, do_authentication API is invoked in session.c (openssh source code), but after that , how sshd executes command received from client is one thing am still trying to figure out.
    – user298537
    Jul 17 '18 at 7:12

It's obvious, you must have protocol in both instance to use it. If you want an alternative, can do with ssh as below.

ssh user@ip "cat > destination" < file.txt

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy