Como enviar um arquivo para um servidor FTP que não encerre corretamente a conexão em caso de sucesso?

1

(movido do SO)

Meu objetivo é enviar um arquivo para um servidor FTP em um dispositivo incorporado. O arquivo é um arquivo de configuração. Quando o arquivo é aceito, o servidor é reinicializado. O que torna isso um desafio é que o dispositivo embutido deixa o soquete aberto ou, caso contrário, não encerra a conexão FTP corretamente.

O servidor responde com o código de resposta 150, que significa "aceito". Em seguida, ele reinicia, mas deixa o soquete aberto.

Estou procurando uma solução. Uma solução é codificar manualmente um cliente FTP em C, outra é usar o cliente FTP integrado no UNIX via script Bash. Nos comentários abaixo, alguém sugeriu curl ou wget / wput.

Primeira tentativa

Na minha primeira tentativa, considerei escrever um cliente FTP em C. Existe uma biblioteca que eu possa usar? Olhando em volta, vejo muitas bibliotecas junky, mas talvez esteja perdendo uma boa.

Segunda tentativa

Em outra tentativa, tentei usar um script Bash para operar o cliente FTP.

O programa a seguir carrega o arquivo, mas depois trava

#!/bin/bash
HOST=192.168.1.10
USER='blah'
PASSWD='blah'
FILE='file1.conf'

ftp -n -i -v $HOST << EOT
ascii
user $USER $PASSWD
put $FILE myconfig.conf
bye
EOT

Isto é o que diz:

Connected to 192.168.1.10 (192.168.1.10).
220 FTP server ready.
530 access denied.
331 Password required.
230 User logged in.
local: somefile.txt remote: newname.txt
227 Entering Passive Mode (192,168,1,10,208,169)
150 ready to take file.
150 Accepting XML configuration file for upload.
818 bytes sent in 4.1e-05 secs (19951.22 Kbytes/sec)
<it hangs here>

Se eu pressionar Ctrl-Z, ele será encerrado. Se eu enviei Ctrl-C ou Ctrl-X, não é bem assim. E quando eu faço Ctrl-Z, ele deixa o processo filho por perto e eu tenho que executar jobs -p | xargs kill -9 para limpar.

Terceira tentativa

Em seguida, tentei a ideia curl :

$ curl -T file1.xml ftp://username:[email protected]/myfile.conf -v

Aqui está a resposta:

*   Trying 192.168.1.10...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connected to 192.168.1.10 (192.168.1.10) port 21 (#0)
< 220 FTP server ready.
> USER admin
< 331 Password required.
> PASS PASS
< 230 User logged in.
> PWD
< 257 "/" is current directory
* Entry path is '/'
> EPSV
* Connect data stream passively
* ftp_perform ends with SECONDARY: 0
< 500 command not supported.
* Failed EPSV attempt. Disabling EPSV
> PASV
< 227 Entering Passive Mode (192,168,1,10,96,232)
*   Trying 192.168.1.10...
* Connecting to 192.168.1.10 (192.168.1.10) port 24808
* Connected to 192.168.1.10 (192.168.1.10) port 21 (#0)
> TYPE I
< 200 command okay
> STOR myfile.conf
< 150 ready to take file.
} [583 bytes data]
* We are completely uploaded and fine
* Remembering we are in dir ""
< 150 Accepting XML configuration file for upload.
* server did not report OK, got 150
100   583    0     0  100   583      0   4827 --:--:-- --:--:-- --:--:--  4858
* Connection #0 to host 192.168.1.10 left intact
curl: (18) server did not report OK, got 150

Isso foi um pouco melhor. Quando eu mando o curl, ele não deixa as coisas por aí como o cliente ftp faz.

Quarta tentativa

Nesta tentativa, tentei wput . Para minha surpresa, recebi uma falha de segmentação.

wput file1.conf ftp://username:[email protected]/myconfig.conf
--09:37:50-- 'file1.conf'
    => ftp://admin:[email protected]:21/myconfig.conf
Connecting to 192.168.1.10:21... connected! 
Logging in as admin ... Logged in!
==> LIST ... done.
Segmentation fault (core dumped)
    
por 010110110101 30.01.2017 / 17:44

1 resposta

3

expect pode detectar a linha bytes sent e, nesse ponto, sair do script:

#!/usr/bin/env expect

set HOST 192.168.1.10
set USER blah
set PASSWD blah
set FILE file1.conf

spawn -noecho ftp -n -i -v $HOST
# TODO possibly some error checking or prompt detection here...
send "ascii\r"
send "user $USER $PASSWD\r"
send "put $FILE myconfig.conf\r"
send "bye\r"
set timeout 60
expect {
    # if paranoid confirm that the amount matches the size of file...
    -ex "bytes sent" { exit }
    timeout { exit 1 }
    eof { exit 1 }
}
    
por 30.01.2017 / 17:56