The tool WinSCP is able to perform a sudo on the remote machine to perform the scp as the sudo user. That leads me to think that this must be possible with the command-line version of scp as well.

Under the wraps, how is WinSCP executing this?

I do not want to work through a solution with a user staging directory. Files might be so big that I am required to post directly using the sudo user. As a result the file copied over, but to my local dir, not the sudo dir.

One solution might be by manually piping over ssh:

tar zcvf -  MyBackups | ssh user@server "cat > /path/to/backup/foo.tgz"

Which I guess could customize to do the sudo as follows:

cat local.txt | ssh user@server "sudo -u sudouser cat > ~/remote_file"

Only problem is that by doing it this way, I have a lot of burden to solve that has been implemented using base scp already. For this and other reasons, I do not want to use this solution either.

Howe can I let scp handle a direct copy to remote using a sudo to change the user so I gain access to it's privileges.

  • Can you please elaborate by what you mean by "provide a sudo user"? Do you just mean that scp has managed to write to a specific location? You say I supsect even the sudo happened succesfully. Don't suspect. Know. If in Unix, ls -ltr /var/log to show which log file has been most recently updated. sudo may log to /var/log/auth.log or /var/log/authlog (depending on operating system). That will confirm if it actually uses sudo, and what command sudo was asked to run. That may help to clarify what happens "under the hood"/"behind the scenes". – TOOGAM Feb 17 '16 at 14:48
  • 1
    You speculate: almost sounds as if "scp" is not as feature complete as "sftp" is. I confirm, with clarity, this is absolutely right. (I'm not necessarily endorsing all the details that led you to that conclusion. I am endorsing the specific resulting conclusion that I just quoted.) scp is a dead protocol, meaning that it has no development future. This is according to OpenSSH FAQ 2.10 which describes why " scp is not standardized", "New features are more likely in sftp" – TOOGAM Feb 17 '16 at 14:54
  • @TOOGAM the sudo user was not able to write, for that I need the subsystem to start and handle the incoming request. The subsystem did start and write, but again as the original user. I can see also that ssh started twice from duplicate welcome log written to the screen, hence I was stating that I got past the sudo. With limited access to system logs at this point, I had to ... Well ... Guess at this point. I will update as I learn more. – YoYo Feb 17 '16 at 17:57
  • What you do you mean "limited access to system logs"? You shouldn't be having limited access to system logs if you're sudo'ing. :) (This statement may be making assumptions, like sudo becoming root rather than a different user.) – TOOGAM Feb 17 '16 at 21:05

Scp works by making an ssh connection to the remote server, then using that connection to execute another scp command on the remote system. The local scp instance and and the remote instance communicate through the ssh link to send or receive files.

OpenSSH scp in particular constructs an scp command string to be run on the remote system. Then it launches ssh to run that command. The eventual ssh command invoked is the equivalent of this:

/path/to/ssh [ssh options...] "scp [scp options...]"
  • /path/to/ssh is normally a built-in path to the ssh program.
  • [ssh options...] is one or more options to the ssh program.
  • "scp [scp options...]" is a single argument containing the scp command and its arguments to run on the remote system.

OpenSSH scp doesn't provide much in the way of options to alter the form of the remote scp command. There's no way to have it invoke something other than "scp", or to insert something like "sudo" in front of the "scp" part.

As you've noticed, scp does have an option to invoke some other program rather than ssh. Someone who knew how could write an ssh wrapper program and have scp invoke the wrapper instead of invoking ssh directly. The wrapper would have to examine its command-line arguments to find the one containing the scp command, alter the command as desired, and then invoke ssh with the altered command-line arguments.

  • In fact from my research so far, the scp2 protocol starts sftp-server at the other end. I will also try to write an ssh wrapper. I guess in a first attempt I could just trap the arguments. – YoYo Feb 17 '16 at 17:49
  • It'd be possible to have a program that acted more or less like scp, but which used sftp for the wire protocol. The OpenSSH scp program is not such a program. – Kenster Feb 17 '16 at 18:15
  • 2
    @JoD. You're misusing the term "protocol". That page is about a command-line utility named "scp2", which uses the SFTP protocol instead of the scp protocol to transfer files. As a practical matter, OpenSSH doesn't include the scp2 program, so relatively few people have access to it. If you're using one of the commercial products that includes the scp2 program, and you're specifically asking about how to use scp2, you should include that information in your question. – Kenster Feb 17 '16 at 20:57
  • Nope just standard openssh. So scp is basically scp1 with scp protocol over ssh, having another scp subsystem started at the remote end? – YoYo Feb 18 '16 at 5:21

How SCP works

The internal workings of scp depends on two undocumented forms of scp, which is scp -f and scp -t. They are basically remote servers listening to stdin and generating data over stdout. Those processes use a protocol similar to what sftp would do. More information can be found at an Oracle Blog.

When scp starts, it will first start a ssh session to start scp -t or scp -f. Your local scp process will then communicate with the remote scp process through stdout and stdin piped to ssh (fully encrypted) and will serve as stdin/stdout for your remote scp session.

How to Customize

The scp command provides an option -s that allows you to customize the program used to setup the remote scp session. It is expected to handle all the options typical for ssh. To help debug how that might look like, we setup a dummy program that just dumps the parameters:


echo $0 $*

We will execute it as follows:

scp -S /tmp/scp-dump.sh /tmp/dump.txt me@server.com:/tmp

And appropriately we get the following output:

/home/me/dump.sh \
    -x -oForwardAgent=no \
    -oPermitLocalCommand=no \
    -oClearAllForwardings=yes \
    -l me -- server.com scp -t /tmp

Line-breaks with backslash were added for readability.

That allows us an opportunity to modify the parameters and commands before we send it to the ssh command.

Setting up sudo

now we can write a program to modify the parameters as needed, start ssh, and use a modified form to start scp -t. We will basically capture the parameters, trap those we want to use internally only add additional ones, and make changes.


add_ssh_option() {
  local option
  if [ $# = 2 ]; then
    option="$1 \"$2\""
  if [ -z "${ssh_options}" ]; then
    ssh_options="${ssh_options} ${option}"

parse_options() {
  local option
  while [ $# > 0 ] ; do
    case $1 in
      -oSudoUser=* )
      -l ) ssh_user=$2 ; shift 2 ;;
      -i ) add_ssh_option "$1" "$2" ; shift 2 ;;
      -- ) shift ; break ;;
      -* ) add_ssh_option "${1}" ; shift ;;
      *  ) break ;;

parse_options "$@"
# To avoid intererence with Standard-In, we change this to
# Strict:
add_ssh_option "-oStrictHostKeyChecking=yes"

if [ -z "${SSH_SUDO_USER}" ]; then
  # As before without sudo
  cat | ssh $ssh_options -l $ssh_user $ssh_host $ssh_command
  exit $?
  # Send standard-in to the customized "scp -t" sink.
  cat | ssh $ssh_options -l $ssh_user $ssh_host sudo -i -u ${SSH_SUDO_USER} $ssh_command
  exit $?

Now we can use the modified scp form:

scp -oSudoUser=other \
    -i /tmp/me-id_rsa \
    /tmp/scp-sudo.sh \
    /tmp/dump.txt \

This works fine for sending a file to remote. However when I retreive a remote file, it somehow hangs. When I break the session (control-c), I do see that the transfer was succesful, but I have somehow an extra file named "0". Wonder if anyone can help me with that?

Better Option: sftp

However sftp is much better.

  1. it has the -S option - allowing to set the entire ssh command line. I had trouble figuring it out and making it to work. I suspect that I do not understand how to correctly bind stdin/stdout from within a shell-ssh wrapper.
  2. it has a -s (lowercase) option - allowing to set just the sub-command responsible for setting up the remote server only. I found this easier to make it work.
  3. You can set the remote path, remote file permissions, do both put/get, etc as per the man pages for sftp.

In this case we just simply

sftp -s "sudo -u sudo-user -- /usr/libexec/openssh/sftp-server" me@server.com

That gave me the happy "sftp>" prompt

Note that the subprogram is sometimes located in different paths, example /usr/libexec/openssh/sftp-server. I would suggest parsing from the "Subsystem sftp" string from within the /etc/ssh/sshd_conf file?

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.