Search code examples
powershellsshcygwinrsync

Magic combination to get rsync on cygwin over ssh working on Windows 10


Firstly, I've read over a dozen similar posts on this, and none of the recommended solutions work for me. But I'm very new to cygwin, so presumably missing something those answers assume.

Use case: I'm trying to create a method to upload changed files to a server from a Windows 10 development machine. This is for some web development where the local build tool first deletes all the existing files and so timestamp comparison is no good. I've tried WinSCP, but it doesn't support checksum synchronisation (even though I'm running proftpd SFTP which does—the WinSCP tracker for that feature hasn't been updated in 3 years). If there is some way to get WinSCP to do this, I'll happily abandon everything else below.

So, rsync over ssh with deltas and --ignore-times seems like a good solution. Note the server only accepts ssh with public key.

I've installed cygwin, and from the cygwin terminal, I have configured ssh with the key, and created a config file. From within a cygwin terminal window, I can now do:

$ ssh server.com

with no problem, and also things like:

$ rsync -e ssh /local/source server.com:/remote/target

Now, the local build tools are run from command line in PowerShell, so I'd like, as the last step, to be able to run a command that will upload the output of the build to the server. Seems simple...

Firstly, in a cygwin terminal, I tried making a bash script called deploy-dev.sh. If I run this from a cygwin terminal, it works fine. But if I run this from PowerShell:

PS C:\cygwin64\bin> .\bash.exe /home/davidl/deploy-dev.sh

I get the following error:

Warning: Identity file /home/davidl/.ssh/key.pem not accessible: No such file or directory.

But it did create a known_hosts file in C:\Users\davidl\.ssh. So I copied the ssh key there. But I still got the same error—still not sure why.

Anyway, on another tack, how about just running rsync.exe from PowerShell, rather than the bash script:

PS C:\cygwin64\bin> .\rsync.exe -e ssh test.txt server.com:/target
Bad owner or permissions on C:\\Users\\davidl/.ssh/config

OK, ignore that for now and try loading the key directly:

PS C:\cygwin64\bin> .\rsync.exe -e "ssh -i C:\Users\davidl\.ssh\key.pem" test.txt [email protected]:/target
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions for 'C:\\Users\\davidl\\.ssh\\key.pem' are too open.

Progress! It's looking at the right file. So on to permissions:

PS C:\cygwin64\bin> .\ls.exe -al C:\Users\davidl\.ssh\
total 14
drwxr-xr-x 1 davidl None    0 Aug  8 19:04 .
drwxr-xr-x 1 davidl None    0 Aug  8 18:33 ..
-rw-r--r-- 1 davidl None 1692 Aug  8 19:02 key.pem
-rw-r--r-- 1 davidl None   94 Aug  8 19:04 config
-rw-r--r-- 1 davidl None  187 Aug  8 19:02 known_hosts

Hmm. That doesn't look right. So, fix it with chgrp and chown as per the many answers posted about such things:

PS C:\cygwin64\bin> .\chgrp.exe -R :Users C:\Users\davidl\.ssh\
/usr/bin/chgrp: invalid group: ':Users'

OK, maybe just permissions will be enough:

PS C:\cygwin64\bin> .\chmod.exe -R 600 C:\Users\davidl\.ssh\
PS C:\cygwin64\bin> .\ls.exe -al C:\Users\davidl\.ssh\
total 14
drwxr-xr-x 1 davidl None    0 Aug  8 19:04 .
drwxr-xr-x 1 davidl None    0 Aug  8 18:33 ..
-rw-r--r-- 1 davidl None 1692 Aug  8 19:02 key.pem
-rw-r--r-- 1 davidl None   94 Aug  8 19:04 config
-rw-r--r-- 1 davidl None  187 Aug  8 19:02 known_hosts

So now I'm stuck. I can't set the right group or permissions on the local files via cygwin, and looking at them from inside a cygwin terminal, the permissions look correct anyway:

davidl@DESKTOP2 /cygdrive/c/Users/davidl/.ssh
$ ls -al
total 14
drwx------+ 1 davidl None      0 Aug  8 19:04 .
drwxrwx---+ 1 SYSTEM SYSTEM    0 Aug  8 18:33 ..
-rw-------+ 1 davidl None     94 Aug  8 19:04 config
-rw-------+ 1 davidl None   1692 Aug  8 19:02 key.pem
-rw-------+ 1 davidl None    187 Aug  8 19:02 known_hosts

Note I've checked this is on an NTFS mount, not FAT32.

How can I most easily accomplish this, apart from having to open a cygwin terminal and run the script manually?


Solution

  • If runnning the script /home/davidl/deploy-dev.sh from inside a default "login" shell works and running as

    .\bash.exe /home/davidl/deploy-dev.sh
    

    fails, than the difference is due to the lack of login settings. You can overcame it with the option -l of bash.

    .\bash.exe -l /home/davidl/dploy-dev.sh
    

    PS: Mintty aka Cygwin Terminal shortcut by default runs a login shell)