🤖

sftpでサーバーサイドcopy

2024/05/24に公開

はじめに

こんなの見つけました
https://www.openssh.com/txt/release-9.0

sftp-server(8): support the "copy-data" extension to allow server-
side copying of files/data, following the design in
draft-ietf-secsh-filexfer-extensions-00. bz2948

  • sftp(1): add a "cp" command to allow the sftp client to perform
    server-side file copies.

ほんとですかね。やってみることにしました。

ちなみに、ですが自分は、docker composeはdocにエイリアスしてます。

dockerを探す

最初はhttps://hub.docker.com/r/atmoz/sftp/のイメージを使ってみました。

$ docker run atmoz/sftp ssh -V
# 中略

OpenSSH_8.4p1 Debian-5+deb11u3, OpenSSL 1.1.1w  11 Sep 2023

versionが低いです。

というわけで下記を使ってみることに。
https://hub.docker.com/r/linuxserver/openssh-server

バージョンは下記でした。

# ssh -V
OpenSSH_9.6p1, OpenSSL 3.1.4 24 Oct 2023

ホストマシン(mac)側のバージョンは下記です

$ ssh -V
OpenSSH_9.6p1, LibreSSL 3.3.6

諸々設定が終わって、sftpするためのdockerのipを調べようとして、

 docker inspect --format='{{json .NetworkSettings.Networks.sftp-practice_default}}' sftp-practice-sshd-1 
template parsing error: template: :1: bad character U+002D '-'

というエラーに遭遇しました。
回避方法あると思いますが、面倒だったので、ディレクトリ名の方を変えました。

また、docker-compose.ymlはこちらです。
https://github.com/na8esin/sftp_practice/blob/main/docker-compose.yml

後ほどrubyのコードが出てきますが、今回は、rubyのdockerは使ってないです。

あと、秘密鍵・公開鍵の置き場所がわかりづらいと思うので、キャプチャも残します(未来の自分へ)。

まずは、sftpコマンドを直接使う

# 長い...
SSH_IP=`docker inspect --format='{{json .NetworkSettings.Networks.sftp_practice_default.IPAddress}}' sftp_practice-sshd-1 | tr -d '"'`

sftp -i ./id_ed25519 -P 2222 linuxserver.io@$SSH_IP

Connected to 192.168.117.2.
sftp> put sample.txt
Uploading sample.txt to /config/sample.txt
sample.txt                                                                                               100%    5     7.5KB/s   00:00    
sftp> cp sample.txt sample2.txt
sftp> ls
logs           sample.txt     sample2.txt    ssh_host_keys  sshd.pid       
sftp> mkdir subdir
sftp> cp sample.txt subdir/sample3.txt
sftp> ls subdir/
subdir/sample3.txt

できそうです。

rubyとかpythonとかから使えないと意味なくない?

おっしゃる通りですね。調べてみましたが、どちらとも直接使えそうなライブラリはなさそうです。

ruby

https://github.com/net-ssh/net-sftp/tree/master/lib/net/sftp/operations
なさそう。

python

https://github.com/paramiko/paramiko/issues/2336
https://stackoverflow.com/questions/77675016/implementing-server-side-file-copy-with-paramiko-sftp-need-guidance-on-custom-e/77675165?noredirect=1#comment136942439_77675165
とのことです。

sshで良くない?

薄々気づいてはいましたが、知識欲には勝てないもので。

sshであれば、rubyでも可能なので、簡単にスクリプトを書いてみました。

ssh.ruby
require 'net/ssh'

Net::SSH.start(
  ENV.fetch('SSH_IP'),
  'linuxserver.io',
  keys: 'id_ed25519',
  port: 2222
  ) do |ssh|
  output = ssh.exec!('cp sample.txt sample6.txt')
end
$ doc exec sshd ls /config                           
logs  sample.txt  sample6.txt  ssh_host_keys  sshd.pid

以上です。

Discussion