📝

Ubuntu 20.04上のcurlでftpサーバーへファイルをアップロードする

2024/07/28に公開

curl: (18) server did not report OK, got 451

curlでftpサーバーへファイルをアップロードするため、下記のようなスクリプトを書きました。

test_1.sh
#!/bin/bash

set -eu

source './.env'
curl --show-error --silent \
    --ftp-method 'nocwd' --ssl-reqd --insecure \
    --user "${USERNAME}:${PASSWORD}" \
    --upload-file 'test.zip' \
    'ftp://ftp.example.com/data/'

Ubuntu 20.04上でスクリプトを実行したところ、下記のエラーが出てアップロードができませんでした。

curl: (18) server did not report OK, got 451

原因

curlの公式リポジトリのIssuesに上がっていました。
既知のバグだったようです。

上記test_1.shを実行したcurlのバージョンは下記の通りです。

$ curl --version
curl 7.68.0 (x86_64-pc-linux-gnu) libcurl/7.68.0 OpenSSL/1.1.1f zlib/1.2.11 brotli/1.0.7 libidn2/2.2.0 libpsl/0.21.0 (+libidn2/2.2.0) libssh/0.9.3/openssl/zlib nghttp2/1.40.0 librtmp/2.3
Release-Date: 2020-01-08
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: AsynchDNS brotli GSS-API HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM NTLM_WB PSL SPNEGO SSL TLS-SRP UnixSockets

このcurlはUbuntu 20.04上のapt installでインストールしたもので、バージョンが古いことがわかりました。
もちろんapt update && apt upgradeを実行しても、これ以上curlのバージョンは上がりません。

対処法

最新版のcurlをダウンロードして使用する

curlの公式サイトのダウンロードページを参照して、最新版のcurlをダウンロードします。

今回は下記のリポジトリからLinux x86_64のバイナリをダウンロードします。

せっかくなので、インストール済のバージョン7.68.0のcurlを使って、バージョン8.8.0のcurlをダウンロードします。

$ curl -sSfL \
> 'https://github.com/stunnel/static-curl/releases/download/8.8.0/curl-linux-x86_64-8.8.0.tar.xz' |
> tar -xvJ
curl
trurl

バージョン8.8.0のcurlをダウンロードできたことを確認します。

$ ./curl --version
curl 8.8.0 (x86_64-pc-linux-gnu) libcurl/8.8.0 OpenSSL/3.3.0 zlib/1.3.1 brotli/1.1.0 zstd/1.5.6 c-ares/1.28.1 libidn2/2.3.7 libpsl/0.21.5 libssh2/1.11.0 nghttp2/1.62.1 nghttp3/1.3.0
Release-Date: 2024-05-22
Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns mqtt pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp ws wss
Features: alt-svc AsynchDNS brotli HSTS HTTP2 HTTP3 HTTPS-proxy IDN IPv6 Largefile libz NTLM PSL SSL threadsafe TLS-SRP TrackMemory UnixSockets zstd

下記のようなスクリプトを書いて実行したところ、無事にファイルをアップロードできました。

test_2.sh
#!/bin/bash

set -eu

source './.env'
./curl --show-error --silent \
    --ftp-method 'nocwd' --ssl-reqd --insecure \
    --user "${USERNAME}:${PASSWORD}" \
    --upload-file 'test.zip' \
    'ftp://ftp.example.com/data/'

冒頭のtest_1.shとの差分は下記のとおりです。

@@ -5,3 +5,3 @@
 source './.env'
-curl --show-error --silent \
+./curl --show-error --silent \
     --ftp-method 'nocwd' --ssl-reqd --insecure \

最新版のcurlをDockerで使用する

Dockerインストール済みの環境なら、curlの公式イメージから最新版のcurlを使用できます。

今回はバージョン8.8.0のイメージを使用します。

$ docker container run --rm 'quay.io/curl/curl:8.8.0' --version
curl 8.8.0 (x86_64-pc-linux-musl) libcurl/8.8.0 OpenSSL/3.1.5 zlib/1.3.1 brotli/1.1.0 libidn2/2.3.4 libpsl/0.21.2 libssh2/1.11.0 nghttp2/1.58.0
Release-Date: 2024-05-22
Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns mqtt pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS brotli GSS-API HSTS HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM PSL SPNEGO SSL threadsafe TLS-SRP UnixSockets

下記のようなスクリプトを書いて実行したところ、無事にファイルをアップロードできました。

test_3.sh
#!/bin/bash

set -eu

source './.env'
docker container run --rm \
    --user "$(id -u):$(id -g)" \
    --workdir '/work' \
    --mount 'type=bind,source=.,target=/work' \
    'quay.io/curl/curl:8.8.0' \
    --show-error --silent \
    --ftp-method 'nocwd' --ssl-reqd --insecure \
    --user "${USERNAME}:${PASSWORD}" \
    --upload-file 'test.zip' \
    'ftp://ftp.example.com/data/'

冒頭のtest_1.shとの差分は下記のとおりです。

@@ -5,3 +5,8 @@
 source './.env'
-curl --show-error --silent \
+docker container run --rm \
+    --user "$(id -u):$(id -g)" \
+    --workdir '/work' \
+    --mount 'type=bind,source=.,target=/work' \
+    'quay.io/curl/curl:8.8.0' \
+    --show-error --silent \
     --ftp-method 'nocwd' --ssl-reqd --insecure \

Ubuntu 24.04にアップグレードする

おそらくこれが最善な対処法でしょう。
Ubuntu 20.04の標準サポート期限が2025年4月に迫っているので、時間ができたらアップグレードしたいです。

まとめ

この記事では、Ubuntu 20.04上のcurlでftpサーバーへファイルをアップロードできない問題とその対処法を紹介しました。
最新版のcurlをダウンロードして使用する、最新版のcurlをDockerで使用する、のいずれかで対処できます。
可能であれば、Ubuntu 24.04にアップグレードすることが最善な対処法でしょう。

Discussion