木领 發表於 2020-8-27 08:24:00

Linux命令cURL详解,并实现文件定时上传到ftp服务器的程序

<h1 id="前言">前言</h1>
<p><img src="https://img-blog.csdnimg.cn/20200826081620584.png"></p>
<p>前段时间群里讨论,想实现某个文件定时上传到服务器要怎么来实现。我记得之前做过<br>
一个项目:<code>为高通的iot模组编写FOTA功能</code>:实现模组可以远程下载升级镜像包,实现版本升级功能。并当时使用的一个超级强大的工具cURL。心血来潮,决定专门写一篇文章,送给需要的朋友。</p>
<p>文章分两部分</p>
<ol>
<li>首先介绍cURL的用法;</li>
<li>实现一个定时上传日志文件的一个简单的程序。<br>
<img src="https://img-blog.csdnimg.cn/2020082608203383.jpg"></li>
</ol>
<h1 id="概念">概念</h1>
<p>cURL 是常用的命令行工具,用来请求 Web 服务器。它的名字就是客户端(client)的 URL 工具的意思。</p>
<p>cURL 的原作者是 Daniel Stenberg (目前是 cURL 的核心开发者),同时也是 IETF HTTPbis 工作组的资深成员。Daniel 在 1998 年创建了 curl 项目,他编写了最初的 curl 版本,并创建了 libcurl 库。到目前为止,代码仓库包括的 24000 次 commit 有超过一半是 Daniel 本人提交的,他依然是项目的核心开发者。Daniel 表示已将 curl 视为自己的孩子。</p>
<p>作为一款强力工具,支持的协议包括 (DICT, FILE, FTP, FTPS, GOPHER, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, TELNET and TFTP),还支持POST、cookies、认证、从指定偏移处下载部分文件等功能,具有用户代理字符串、限速、文件大小、进度条、cookie支持、用户认证、断点续传等特征。</p>
<h1 id="一命令的安装">一、命令的安装</h1>
<pre><code class="language-bash">sudo apt-get install curl
</code></pre>
<h1 id="二curl命令语法">二、cURL命令语法:</h1>
<pre><code class="language-bash">curl
</code></pre>
<h1 id="三url格式">三、URL格式</h1>
<p>URL的格式定义要参考 RFC 1808 。</p>
<pre><code class="language-bash">地址:http://www.w3.org/Addressing/rfc1808.txt
《Relative Uniform Resource Locators 》
</code></pre>
<p>URL由三部分组成:资源类型、存放资源的主机域名、资源文件名。<br>
也可认为由4部分组成:<strong><code>协议、主机、端口、路径</code></strong><br>
URL的一般语法格式为:</p>
<pre><code class="language-bash">protocol :// hostname[:port] / path / [;parameters][?query]#fragment
</code></pre>
<p>(带方括号[]的为可选项)。</p>
<h4 id="protocol协议">protocol(协议)</h4>
<p>指定使用的传输协议,下表列出 protocol 属性的有效方案名称。 最常用的是HTTP协议,它也是WWW中应用最广的协议。</p>
<ul>
<li>file 资源是本地计算机上的文件。格式file:///,注意后边应是三个斜杠。</li>
<li>ftp 通过 FTP访问资源。格式 FTP://</li>
<li>gopher 通过 Gopher 协议访问该资源。</li>
<li>http 通过 HTTP 访问该资源。 格式 HTTP://</li>
<li>https 通过安全的 HTTPS 访问该资源。 格式 HTTPS://</li>
<li>mailto 资源为电子邮件地址,通过 SMTP 访问。 格式 mailto:</li>
<li>MMS 通过 支持MMS(流媒体)协议的播放该资源。(代表软件:Windows Media Player)格式 MMS://</li>
<li>ed2k 通过 支持ed2k(专用下载链接)协议的P2P软件访问该资源。(代表软件:电驴) 格式 ed2k://</li>
<li>Flashget 通过 支持Flashget:(专用下载链接)协议的P2P软件访问该资源。(代表软件:快车) 格式 Flashget://</li>
<li>thunder 通过 支持thunder(专用下载链接)协议的P2P软件访问该资源。(代表软件:迅雷) 格式 thunder://</li>
<li>news 通过 NNTP 访问该资源。</li>
</ul>
<h4 id="hostname主机名">hostname(主机名)</h4>
<p>是指存放资源的服务器的域名系统(DNS) 主机名或 IP 地址。有时,在主机名前也可以包含连接到服务器所需的用户名和密码(格式:username:password@hostname)。</p>
<h4 id="port端口号">port(端口号)</h4>
<p>整数,可选,省略时使用方案的默认端口,各种传输协议都有默认的端口号,如http的默认端口为80。如果输入时省略,则使用默认端口号。有时候出于安全或其他考虑,可以在服务器上对端口进行重定义,即采用非标准端口号,此时,URL中就不能省略端口号这一项。</p>
<h4 id="path路径">path(路径)</h4>
<p>由零或多个“/”符号隔开的字符串,一般用来表示主机上的一个目录或文件地址。</p>
<h4 id="parameters参数">parameters(参数)</h4>
<p>这是用于指定特殊参数的可选项。</p>
<h4 id="query查询">query(查询)</h4>
<p>可选,用于给动态网页(如使用CGI、ISAPI、PHP/JSP/ASP/ASP.NET等技术制作的网页)传递参数,可有多个参数,用“&amp;”符号隔开,每个参数的名和值用“=”符号隔开。</p>
<h4 id="fragment信息片断">fragment(信息片断)</h4>
<p>字符串,用于指定网络资源中的片断。例如一个网页中有多个名词解释,可使用fragment直接定位到某一名词解释。</p>
<h1 id="四curl命令参数详解">四、curl命令参数详解:</h1>
<p>  由于linux curl功能十分强大,所以命令参数十分多,下表只筛选出来部分常用的参数,更多参数请运行“man curl”命令查看。</p>
<table>
<thead>
<tr>
<th style="text-align: left">参数</th>
<th style="text-align: left">功能</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left">-a/--append</td>
<td style="text-align: left">上传文件时,附加到目标文件</td>
</tr>
<tr>
<td style="text-align: left">-A/--user-agent <string></string></td>
<td style="text-align: left">设置用户代理发送给服务器</td>
</tr>
<tr>
<td style="text-align: left">-anyauth</td>
<td style="text-align: left">可以使用“任何”身份验证方法</td>
</tr>
<tr>
<td style="text-align: left">-b/--cookie &lt;name=string/file&gt;</td>
<td style="text-align: left">cookie字符串或文件读取位置</td>
</tr>
<tr>
<td style="text-align: left">--basic</td>
<td style="text-align: left">使用HTTP基本验证</td>
</tr>
<tr>
<td style="text-align: left">-B/--use-ascii</td>
<td style="text-align: left">使用ASCII /文本传输</td>
</tr>
<tr>
<td style="text-align: left">-c/--cookie-jar <file></file></td>
<td style="text-align: left">操作结束后把cookie写入到这个文件中</td>
</tr>
<tr>
<td style="text-align: left">-C/--continue-at <offset></offset></td>
<td style="text-align: left">断点续转</td>
</tr>
<tr>
<td style="text-align: left">-d/--data <data></data></td>
<td style="text-align: left">HTTP POST方式传送数据</td>
</tr>
<tr>
<td style="text-align: left">--data-ascii <data></data></td>
<td style="text-align: left">以ascii的方式post数据</td>
</tr>
<tr>
<td style="text-align: left">--data-binary <data></data></td>
<td style="text-align: left">以二进制的方式post数据</td>
</tr>
<tr>
<td style="text-align: left">--negotiate</td>
<td style="text-align: left">使用HTTP身份验证</td>
</tr>
<tr>
<td style="text-align: left">--digest</td>
<td style="text-align: left">使用数字身份验证</td>
</tr>
<tr>
<td style="text-align: left">--disable-eprt</td>
<td style="text-align: left">禁止使用EPRT或LPRT</td>
</tr>
<tr>
<td style="text-align: left">--disable-epsv</td>
<td style="text-align: left">禁止使用EPSV</td>
</tr>
<tr>
<td style="text-align: left">-D/--dump-header <file></file></td>
<td style="text-align: left">把header信息写入到该文件中</td>
</tr>
<tr>
<td style="text-align: left">--egd-file <file></file></td>
<td style="text-align: left">为随机数据(SSL)设置EGD socket路径</td>
</tr>
<tr>
<td style="text-align: left">--tcp-nodelay</td>
<td style="text-align: left">使用TCP_NODELAY选项</td>
</tr>
<tr>
<td style="text-align: left">-e/--referer</td>
<td style="text-align: left">来源网址</td>
</tr>
<tr>
<td style="text-align: left">-E/--cert &lt;cert[:passwd]&gt;</td>
<td style="text-align: left">客户端证书文件和密码 (SSL)</td>
</tr>
<tr>
<td style="text-align: left">--cert-type <type></type></td>
<td style="text-align: left">证书文件类型 (DER/PEM/ENG) (SSL)</td>
</tr>
<tr>
<td style="text-align: left">--key <key></key></td>
<td style="text-align: left">私钥文件名 (SSL)</td>
</tr>
<tr>
<td style="text-align: left">--key-type <type></type></td>
<td style="text-align: left">私钥文件类型 (DER/PEM/ENG) (SSL)</td>
</tr>
<tr>
<td style="text-align: left">--pass <pass></pass></td>
<td style="text-align: left">私钥密码 (SSL)</td>
</tr>
<tr>
<td style="text-align: left">--engine <eng></eng></td>
<td style="text-align: left">加密引擎使用 (SSL). "--engine list" for list</td>
</tr>
<tr>
<td style="text-align: left">--cacert <file></file></td>
<td style="text-align: left">CA证书 (SSL)</td>
</tr>
<tr>
<td style="text-align: left">--capath <directory></directory></td>
<td style="text-align: left">CA目录 (made using c_rehash) to verify peer against (SSL)</td>
</tr>
<tr>
<td style="text-align: left">--ciphers <list></list></td>
<td style="text-align: left">SSL密码</td>
</tr>
<tr>
<td style="text-align: left">--compressed</td>
<td style="text-align: left">要求返回是压缩的形势 (using deflate or gzip)</td>
</tr>
<tr>
<td style="text-align: left">--connect-timeout <seconds></seconds></td>
<td style="text-align: left">设置最大请求时间</td>
</tr>
<tr>
<td style="text-align: left">--create-dirs</td>
<td style="text-align: left">建立本地目录的目录层次结构</td>
</tr>
<tr>
<td style="text-align: left">--crlf</td>
<td style="text-align: left">上传是把LF转变成CRLF</td>
</tr>
<tr>
<td style="text-align: left">-f/--fail</td>
<td style="text-align: left">连接失败时不显示http错误</td>
</tr>
<tr>
<td style="text-align: left">--ftp-create-dirs</td>
<td style="text-align: left">如果远程目录不存在,创建远程目录</td>
</tr>
<tr>
<td style="text-align: left">--ftp-method </td>
<td style="text-align: left">控制CWD的使用</td>
</tr>
<tr>
<td style="text-align: left">--ftp-pasv</td>
<td style="text-align: left">使用 PASV/EPSV 代替端口</td>
</tr>
<tr>
<td style="text-align: left">--ftp-skip-pasv-ip</td>
<td style="text-align: left">使用PASV的时候,忽略该IP地址</td>
</tr>
<tr>
<td style="text-align: left">--ftp-ssl</td>
<td style="text-align: left">尝试用 SSL/TLS 来进行ftp数据传输</td>
</tr>
<tr>
<td style="text-align: left">--ftp-ssl-reqd</td>
<td style="text-align: left">要求用 SSL/TLS 来进行ftp数据传输</td>
</tr>
<tr>
<td style="text-align: left">-F/--form &lt;name=content&gt;</td>
<td style="text-align: left">模拟http表单提交数据</td>
</tr>
<tr>
<td style="text-align: left">--form-string &lt;name=string&gt;</td>
<td style="text-align: left">模拟http表单提交数据</td>
</tr>
<tr>
<td style="text-align: left">-g/--globoff</td>
<td style="text-align: left">禁用网址序列和范围使用{}和[]</td>
</tr>
<tr>
<td style="text-align: left">-G/--get</td>
<td style="text-align: left">以get的方式来发送数据</td>
</tr>
<tr>
<td style="text-align: left">-H/--header <line></line></td>
<td style="text-align: left">自定义头信息传递给服务器</td>
</tr>
<tr>
<td style="text-align: left">--ignore-content-length</td>
<td style="text-align: left">忽略的HTTP头信息的长度</td>
</tr>
<tr>
<td style="text-align: left">-i/--include</td>
<td style="text-align: left">输出时包括protocol头信息</td>
</tr>
<tr>
<td style="text-align: left">-I/--head</td>
<td style="text-align: left">只显示请求头信息</td>
</tr>
<tr>
<td style="text-align: left">-j/--junk-session-cookies</td>
<td style="text-align: left">读取文件进忽略session cookie</td>
</tr>
<tr>
<td style="text-align: left">--interface <interface></interface></td>
<td style="text-align: left">使用指定网络接口/地址</td>
</tr>
<tr>
<td style="text-align: left">--krb4 <level></level></td>
<td style="text-align: left">使用指定安全级别的krb4</td>
</tr>
<tr>
<td style="text-align: left">-k/--insecure</td>
<td style="text-align: left">允许不使用证书到SSL站点</td>
</tr>
<tr>
<td style="text-align: left">-K/--config</td>
<td style="text-align: left">指定的配置文件读取</td>
</tr>
<tr>
<td style="text-align: left">-l/--list-only</td>
<td style="text-align: left">列出ftp目录下的文件名称</td>
</tr>
<tr>
<td style="text-align: left">--limit-rate <rate></rate></td>
<td style="text-align: left">设置传输速度</td>
</tr>
<tr>
<td style="text-align: left">--local-port<num></num></td>
<td style="text-align: left">强制使用本地端口号</td>
</tr>
<tr>
<td style="text-align: left">-m/--max-time <seconds></seconds></td>
<td style="text-align: left">设置最大传输时间</td>
</tr>
<tr>
<td style="text-align: left">--max-redirs <num></num></td>
<td style="text-align: left">设置最大读取的目录数</td>
</tr>
<tr>
<td style="text-align: left">--max-filesize <bytes></bytes></td>
<td style="text-align: left">设置最大下载的文件总量</td>
</tr>
<tr>
<td style="text-align: left">-M/--manual</td>
<td style="text-align: left">显示全手动</td>
</tr>
<tr>
<td style="text-align: left">-n/--netrc</td>
<td style="text-align: left">从netrc文件中读取用户名和密码</td>
</tr>
<tr>
<td style="text-align: left">--netrc-optional</td>
<td style="text-align: left">使用 .netrc 或者 URL来覆盖-n</td>
</tr>
<tr>
<td style="text-align: left">--ntlm</td>
<td style="text-align: left">使用 HTTP NTLM 身份验证</td>
</tr>
<tr>
<td style="text-align: left">-N/--no-buffer</td>
<td style="text-align: left">禁用缓冲输出</td>
</tr>
<tr>
<td style="text-align: left">-o/--output</td>
<td style="text-align: left">把输出写到该文件中</td>
</tr>
<tr>
<td style="text-align: left">-O/--remote-name</td>
<td style="text-align: left">把输出写到该文件中,保留远程文件的文件名</td>
</tr>
<tr>
<td style="text-align: left">-p/--proxytunnel</td>
<td style="text-align: left">使用HTTP代理</td>
</tr>
<tr>
<td style="text-align: left">--proxy-anyauth</td>
<td style="text-align: left">选择任一代理身份验证方法</td>
</tr>
<tr>
<td style="text-align: left">--proxy-basic</td>
<td style="text-align: left">在代理上使用基本身份验证</td>
</tr>
<tr>
<td style="text-align: left">--proxy-digest</td>
<td style="text-align: left">在代理上使用数字身份验证</td>
</tr>
<tr>
<td style="text-align: left">--proxy-ntlm</td>
<td style="text-align: left">在代理上使用ntlm身份验证</td>
</tr>
<tr>
<td style="text-align: left">-P/--ftp-port </address></td>
<td style="text-align: left">使用端口地址,而不是使用PASV</td>
</tr>
<tr>
<td style="text-align: left">-q</td>
<td style="text-align: left">作为第一个参数,关闭 .curlrc</td>
</tr>
<tr>
<td style="text-align: left">-Q/--quote <cmd></cmd></td>
<td style="text-align: left">文件传输前,发送命令到服务器</td>
</tr>
<tr>
<td style="text-align: left">-r/--range <range></range></td>
<td style="text-align: left">检索来自HTTP/1.1或FTP服务器字节范围</td>
</tr>
<tr>
<td style="text-align: left">--range-file</td>
<td style="text-align: left">读取(SSL)的随机文件</td>
</tr>
<tr>
<td style="text-align: left">-R/--remote-time</td>
<td style="text-align: left">在本地生成文件时,保留远程文件时间</td>
</tr>
<tr>
<td style="text-align: left">--retry <num></num></td>
<td style="text-align: left">传输出现问题时,重试的次数</td>
</tr>
<tr>
<td style="text-align: left">--retry-delay <seconds></seconds></td>
<td style="text-align: left">传输出现问题时,设置重试间隔时间</td>
</tr>
<tr>
<td style="text-align: left">--retry-max-time <seconds></seconds></td>
<td style="text-align: left">传输出现问题时,设置最大重试时间</td>
</tr>
<tr>
<td style="text-align: left">-s/--silent</td>
<td style="text-align: left">静默模式。不输出任何东西</td>
</tr>
<tr>
<td style="text-align: left">-S/--show-error</td>
<td style="text-align: left">显示错误</td>
</tr>
<tr>
<td style="text-align: left">--socks4 &lt;host[:port]&gt;</td>
<td style="text-align: left">用socks4代理给定主机和端口</td>
</tr>
<tr>
<td style="text-align: left">--socks5 &lt;host[:port]&gt;</td>
<td style="text-align: left">用socks5代理给定主机和端口</td>
</tr>
<tr>
<td style="text-align: left">--stderr <file></file></td>
<td style="text-align: left"></td>
</tr>
<tr>
<td style="text-align: left">-t/--telnet-option &lt;OPT=val&gt;</td>
<td style="text-align: left">Telnet选项设置</td>
</tr>
<tr>
<td style="text-align: left">--trace <file></file></td>
<td style="text-align: left">对指定文件进行debug</td>
</tr>
<tr>
<td style="text-align: left">--trace-ascii <file></file></td>
<td style="text-align: left">Like --跟踪但没有hex输出</td>
</tr>
<tr>
<td style="text-align: left">--trace-time</td>
<td style="text-align: left">跟踪/详细输出时,添加时间戳</td>
</tr>
<tr>
<td style="text-align: left">-T/--upload-file <file></file></td>
<td style="text-align: left">上传文件</td>
</tr>
<tr>
<td style="text-align: left">--url <url></url></td>
<td style="text-align: left">Spet URL to work with</td>
</tr>
<tr>
<td style="text-align: left">-u/--user &lt;user[:password]&gt;</td>
<td style="text-align: left">设置服务器的用户和密码</td>
</tr>
<tr>
<td style="text-align: left">-U/--proxy-user &lt;user[:password]&gt;</td>
<td style="text-align: left">设置代理用户名和密码</td>
</tr>
<tr>
<td style="text-align: left">-w/--write-out </td>
<td style="text-align: left">什么输出完成后</td>
</tr>
<tr>
<td style="text-align: left">-x/--proxy &lt;host[:port]&gt;</td>
<td style="text-align: left">在给定的端口上使用HTTP代理</td>
</tr>
<tr>
<td style="text-align: left">-X/--request <command></command></td>
<td style="text-align: left">指定什么命令</td>
</tr>
<tr>
<td style="text-align: left">-y/--speed-time</td>
<td style="text-align: left">放弃限速所要的时间,默认为30</td>
</tr>
<tr>
<td style="text-align: left">-Y/--speed-limit</td>
<td style="text-align: left">停止传输速度的限制,速度时间</td>
</tr>
</tbody>
</table>
<h1 id="五linux-curl命令退出码">五、Linux curl命令退出码:</h1>
<p>下面是linux curl命令的错误代码和她们的相应的错误消息,命令执行错误的时候可以通过错误码来查看出错原因,方便开发调试。</p>
<table>
<thead>
<tr>
<th>退 出 码</th>
<th style="text-align: left">错误描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td style="text-align: left">Unsupported protocol. This build of curl has no support for this protocol.</td>
</tr>
<tr>
<td>2</td>
<td style="text-align: left">Failed to initialize.</td>
</tr>
<tr>
<td>3</td>
<td style="text-align: left">URL malformed. The syntax was not correct.</td>
</tr>
<tr>
<td>5</td>
<td style="text-align: left">Couldn't resolve proxy. The given proxy host could not be resolved.</td>
</tr>
<tr>
<td>6</td>
<td style="text-align: left">Couldn't resolve host. The given remote host was not resolved.</td>
</tr>
<tr>
<td>7</td>
<td style="text-align: left">Failed to connect to host.</td>
</tr>
<tr>
<td>8</td>
<td style="text-align: left">FTP weird server reply. The server sent data curl couldn't parse.</td>
</tr>
<tr>
<td>9</td>
<td style="text-align: left">FTP access denied. The server denied login or denied access to the particular resource or directory you wanted to reach. Most often you tried to change to a directory that doesn't exist on the server.</td>
</tr>
<tr>
<td>11</td>
<td style="text-align: left">FTP weird PASS reply. Curl couldn't parse the reply sent to the PASS request.</td>
</tr>
<tr>
<td>13</td>
<td style="text-align: left">FTP weird PASV reply, Curl couldn't parse the reply sent to the PASV request.</td>
</tr>
<tr>
<td>14</td>
<td style="text-align: left">FTP weird 227 format. Curl couldn't parse the 227-line the server sent.</td>
</tr>
<tr>
<td>15</td>
<td style="text-align: left">FTP can't get host. Couldn't resolve the host IP we got in the 227-line.</td>
</tr>
<tr>
<td>17</td>
<td style="text-align: left">FTP couldn't set binary. Couldn't change transfer method to binary.</td>
</tr>
<tr>
<td>18</td>
<td style="text-align: left">Partial file. Only a part of the file was transferred.</td>
</tr>
<tr>
<td>19</td>
<td style="text-align: left">FTP couldn't download/access the given file, the RETR (or similar) command failed.</td>
</tr>
<tr>
<td>21</td>
<td style="text-align: left">FTP quote error. A quote command returned error from the server.</td>
</tr>
<tr>
<td>22</td>
<td style="text-align: left">HTTP page not retrieved. The requested url was not found or returned another error with the HTTP error code being 400 or above. This return code only appears if -f/--fail is used.</td>
</tr>
<tr>
<td>23</td>
<td style="text-align: left">Write error. Curl couldn't write data to a local filesystem or similar.</td>
</tr>
<tr>
<td>25</td>
<td style="text-align: left">FTP couldn't STOR file. The server denied the STOR operation, used for FTP uploading.</td>
</tr>
<tr>
<td>26</td>
<td style="text-align: left">Read error. Various reading problems.</td>
</tr>
<tr>
<td>27</td>
<td style="text-align: left">Out of memory. A memory allocation request failed.</td>
</tr>
<tr>
<td>28</td>
<td style="text-align: left">Operation timeout. The specified time-out period was reached according to the conditions.</td>
</tr>
<tr>
<td>30</td>
<td style="text-align: left">FTP PORT failed. The PORT command failed. Not all FTP servers support the PORT command, try doing a transfer using PASV instead!</td>
</tr>
<tr>
<td>31</td>
<td style="text-align: left">FTP couldn't use REST. The REST command failed. This command is used for resumed FTP transfers.</td>
</tr>
<tr>
<td>33</td>
<td style="text-align: left">HTTP range error. The range "command" didn't work.</td>
</tr>
<tr>
<td>34</td>
<td style="text-align: left">HTTP post error. Internal post-request generation error.</td>
</tr>
<tr>
<td>35</td>
<td style="text-align: left">SSL connect error. The SSL handshaking failed.</td>
</tr>
<tr>
<td>36</td>
<td style="text-align: left">FTP bad download resume. Couldn't continue an earlier aborted download.</td>
</tr>
<tr>
<td>37</td>
<td style="text-align: left">FILE couldn't read file. Failed to open the file. Permissions?</td>
</tr>
<tr>
<td>38</td>
<td style="text-align: left">LDAP cannot bind. LDAP bind operation failed.</td>
</tr>
<tr>
<td>39</td>
<td style="text-align: left">LDAP search failed.</td>
</tr>
<tr>
<td>41</td>
<td style="text-align: left">Function not found. A required LDAP function was not found.</td>
</tr>
<tr>
<td>42</td>
<td style="text-align: left">Aborted by callback. An application told curl to abort the operation.</td>
</tr>
<tr>
<td>43</td>
<td style="text-align: left">Internal error. A function was called with a bad parameter.</td>
</tr>
<tr>
<td>45</td>
<td style="text-align: left">Interface error. A specified outgoing interface could not be used.</td>
</tr>
<tr>
<td>47</td>
<td style="text-align: left">Too many redirects. When following redirects, curl hit the maximum amount.</td>
</tr>
<tr>
<td>48</td>
<td style="text-align: left">Unknown TELNET option specified.</td>
</tr>
<tr>
<td>49</td>
<td style="text-align: left">Malformed telnet option.</td>
</tr>
<tr>
<td>51</td>
<td style="text-align: left">The peer's SSL certificate or SSH MD5 fingerprint was not ok.</td>
</tr>
<tr>
<td>52</td>
<td style="text-align: left">The server didn't reply anything, which here is considered an error.</td>
</tr>
<tr>
<td>53</td>
<td style="text-align: left">SSL crypto engine not found.</td>
</tr>
<tr>
<td>54</td>
<td style="text-align: left">Cannot set SSL crypto engine as default.</td>
</tr>
<tr>
<td>55</td>
<td style="text-align: left">Failed sending network data.</td>
</tr>
<tr>
<td>56</td>
<td style="text-align: left">Failure in receiving network data.</td>
</tr>
<tr>
<td>58</td>
<td style="text-align: left">Problem with the local certificate.</td>
</tr>
<tr>
<td>59</td>
<td style="text-align: left">Couldn't use specified SSL cipher.</td>
</tr>
<tr>
<td>60</td>
<td style="text-align: left">Peer certificate cannot be authenticated with known CA certificates.</td>
</tr>
<tr>
<td>61</td>
<td style="text-align: left">Unrecognized transfer encoding.</td>
</tr>
<tr>
<td>62</td>
<td style="text-align: left">Invalid LDAP URL.</td>
</tr>
<tr>
<td>63</td>
<td style="text-align: left">Maximum file size exceeded.</td>
</tr>
<tr>
<td>64</td>
<td style="text-align: left">Requested FTP SSL level failed.</td>
</tr>
<tr>
<td>65</td>
<td style="text-align: left">Sending the data requires a rewind that failed.</td>
</tr>
<tr>
<td>66</td>
<td style="text-align: left">Failed to initialize SSL Engine.</td>
</tr>
<tr>
<td>67</td>
<td style="text-align: left">The user name, password, or similar was not accepted and curl failed to log in.</td>
</tr>
<tr>
<td>68</td>
<td style="text-align: left">File not found on TFTP server.</td>
</tr>
<tr>
<td>69</td>
<td style="text-align: left">Permission problem on TFTP server.</td>
</tr>
<tr>
<td>70</td>
<td style="text-align: left">Out of disk space on TFTP server.</td>
</tr>
<tr>
<td>71</td>
<td style="text-align: left">Illegal TFTP operation.</td>
</tr>
<tr>
<td>72</td>
<td style="text-align: left">Unknown TFTP transfer ID.</td>
</tr>
<tr>
<td>73</td>
<td style="text-align: left">File already exists (TFTP).</td>
</tr>
<tr>
<td>74</td>
<td style="text-align: left">No such user (TFTP).</td>
</tr>
<tr>
<td>75</td>
<td style="text-align: left">Character conversion failed.</td>
</tr>
<tr>
<td>76</td>
<td style="text-align: left">Character conversion functions required.</td>
</tr>
<tr>
<td>77</td>
<td style="text-align: left">Problem with reading the SSL CA cert (path? access rights?).</td>
</tr>
<tr>
<td>78</td>
<td style="text-align: left">The resource referenced in the URL does not exist.</td>
</tr>
<tr>
<td>79</td>
<td style="text-align: left">An unspecified error occurred during the SSH session.</td>
</tr>
<tr>
<td>80</td>
<td style="text-align: left">Failed to shut down the SSL connection.</td>
</tr>
<tr>
<td>82</td>
<td style="text-align: left">Could not load CRL file, missing or wrong format (added in 7.19.0).</td>
</tr>
<tr>
<td>83</td>
<td style="text-align: left">Issuer check failed (added in 7.19.0).</td>
</tr>
<tr>
<td>XX</td>
<td style="text-align: left">More error codes will appear here in future releases. The existing ones are meant to never change.</td>
</tr>
</tbody>
</table>
<h1 id="六用法演示">六、用法演示:</h1>
<p>为节省篇幅,部分操作不再贴上执行结果。</p>
<h3 id="1查看网页源码">1、查看网页源码</h3>
<p>直接在curl命令后加上网址,就可以看到网页源码。我们以网址www.sina.com为例(选择该网址,主要因为它的网页代码较短):</p>
<pre><code class="language-bash">root@ubuntu:/home/peng# curl www.sohu.com
&lt;html&gt;
&lt;head&gt;&lt;title&gt;307 Temporary Redirect&lt;/title&gt;&lt;/head&gt;
&lt;body bgcolor="white"&gt;
&lt;center&gt;&lt;h1&gt;307 Temporary Redirect&lt;/h1&gt;&lt;/center&gt;
&lt;hr&gt;&lt;center&gt;nginx&lt;/center&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>执行结果显示 <code>307 Temporary Redirect</code>,说明该网址需要重定向。</p>
<p>如果要把这个网页保存下来,可以使用<code>-o</code>参数,这就相当于使用wget命令了。</p>
<pre><code class="language-bash">curl -o [文件名] www.sohu.com
</code></pre>
<h3 id="2自动跳转">2、自动跳转</h3>
<p>有的网址是自动跳转的。使用<code>-L</code>参数,curl就会跳转到新的网址。</p>
<pre><code class="language-bash">curl -L www.sohu.com
</code></pre>
<p>键入上面的命令,结果就自动跳转为www.sohu.com.cn。</p>
<h3 id="3显示头信息">3、显示头信息</h3>
<p><code>-i</code>参数可以显示http response的头信息,连同网页代码一起。</p>
<pre><code class="language-bash">root@ubuntu:/home/peng/driver/test#curl -i www.sohu.com
HTTP/1.1 307 Temporary Redirect
Content-Type: text/html
Content-Length: 180
Connection: keep-alive
Server: nginx
Date: Tue, 25 Aug 2020 10:10:54 GMT
Location: https://www.sohu.com/
FSS-Cache: from 9790436.18244590.10468709
FSS-Proxy: Powered by 2384755.3433341.3062915

&lt;html&gt;
&lt;head&gt;&lt;title&gt;307 Temporary Redirect&lt;/title&gt;&lt;/head&gt;
&lt;body bgcolor="white"&gt;
&lt;center&gt;&lt;h1&gt;307 Temporary Redirect&lt;/h1&gt;&lt;/center&gt;
&lt;hr&gt;&lt;center&gt;nginx&lt;/center&gt;
&lt;/body&gt;
&lt;/html&gt;

</code></pre>
<p><code>-I</code>参数则是只显示http response的头信息。</p>
<h3 id="4显示通信过程">4、显示通信过程</h3>
<p><code>-v</code>参数可以显示一次http通信的整个过程,包括端口连接和http request头信息。</p>
<pre><code class="language-bash">root@ubuntu:/home/peng/driver/test#curl -v www.sohu.com
* About to connect() to www.sohu.com port 80 (#0)
*   Trying 240e:83:201:3700::5... connected
&gt; GET / HTTP/1.1
&gt; User-Agent: curl/7.22.0 (i686-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
&gt; Host: www.sohu.com
&gt; Accept: */*
&gt;
&lt; HTTP/1.1 307 Temporary Redirect
&lt; Content-Type: text/html
&lt; Content-Length: 180
&lt; Connection: keep-alive
&lt; Server: nginx
&lt; Date: Tue, 25 Aug 2020 10:11:49 GMT
&lt; Location: https://www.sohu.com/
&lt; FSS-Cache: from 9855973.18375663.10534247
&lt; FSS-Proxy: Powered by 2450292.3564414.3128453
&lt;
&lt;html&gt;
&lt;head&gt;&lt;title&gt;307 Temporary Redirect&lt;/title&gt;&lt;/head&gt;
&lt;body bgcolor="white"&gt;
&lt;center&gt;&lt;h1&gt;307 Temporary Redirect&lt;/h1&gt;&lt;/center&gt;
&lt;hr&gt;&lt;center&gt;nginx&lt;/center&gt;
&lt;/body&gt;
&lt;/html&gt;
* Connection #0 to host www.sohu.com left intact
* Closing connection #0

</code></pre>
<p>如果你觉得上面的信息还不够,那么下面的命令可以查看更详细的通信过程。</p>
<pre><code class="language-bash">curl --trace output.txt www.sohu.com
</code></pre>
<p>或者</p>
<pre><code class="language-bash">curl --trace-ascii output.txt www.sohu.com
</code></pre>
<p>运行后,请打开output.txt文件查看。</p>
<h3 id="5发送表单信息">5、发送表单信息</h3>
<p>发送表单信息有GET和POST两种方法。GET方法相对简单,只要把数据附在网址后面就行。</p>
<pre><code class="language-bash">curl example.com/form.cgi?data=xxx
</code></pre>
<p>POST方法必须把数据和网址分开,curl就要用到--data参数。</p>
<pre><code class="language-bash">curl -X POST --data "data=xxx" example.com/form.cgi
</code></pre>
<p>如果你的数据没有经过表单编码,还可以让curl为你编码,参数是<code>--data-urlencode</code>。</p>
<pre><code class="language-bash">curl -X POST--data-urlencode "date=April 1" example.com/form.cgi
</code></pre>
<h3 id="6http动词">6、HTTP动词</h3>
<p>curl默认的HTTP动词是GET,使用<code>-X</code>参数可以支持其他动词。</p>
<pre><code class="language-bash">curl -X POST www.example.com
curl -X DELETE www.example.com
</code></pre>
<h3 id="7文件上传">7、文件上传</h3>
<p>假定文件上传的表单是下面这样:</p>
<pre><code class="language-bash">&lt;form method="POST" enctype='multipart/form-data' action="upload.cgi"&gt;
 &lt;input type=file name=upload&gt;
 &lt;input type=submit name=press value="OK"&gt;
&lt;/form&gt;
</code></pre>
<p>你可以用curl这样上传文件:</p>
<pre><code class="language-bash">curl --form upload=@localfilename --form press=OK
</code></pre>
<h3 id="8referer字段">8、Referer字段</h3>
<p>有时你需要在http request头信息中,提供一个referer字段,表示你是从哪里跳转过来的。</p>
<pre><code class="language-bash">curl --referer http://www.example.com http://www.example.com
</code></pre>
<h3 id="9user-agent字段">9、User Agent字段</h3>
<p>这个字段是用来表示客户端的设备信息。服务器有时会根据这个字段,针对不同设备,返回不同格式的网页,比如手机版和桌面版。</p>
<p>iPhone4的User Agent是</p>
<pre><code class="language-bash">Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7
</code></pre>
<p>curl可以这样模拟:</p>
<pre><code class="language-bash">curl --user-agent ""
</code></pre>
<h3 id="10cookie">10、cookie</h3>
<p>使用<code>--cookie</code>参数,可以让curl发送cookie。</p>
<pre><code class="language-bash">curl --cookie "name=xxx" www.example.com
</code></pre>
<p>至于具体的cookie的值,可以从http response头信息的<code>Set-Cookie</code>字段中得到。</p>
<p><code>-c cookie-file</code>可以保存服务器返回的cookie到文件,<code>-b cookie-file</code>可以使用这个文件作为cookie信息,进行后续的请求。</p>
<pre><code class="language-bash">curl -c cookies http://example.com
curl -b cookies http://example.com
</code></pre>
<h3 id="11增加头信息">11、增加头信息</h3>
<p>有时需要在http request之中,自行增加一个头信息。<code>--header</code>参数就可以起到这个作用。</p>
<pre><code class="language-bash">$ curl --header "Content-Type:application/json" http://example.com
</code></pre>
<h3 id="12认证">12、认证</h3>
<p>使用curl选项 -u 可以完成HTTP或者FTP的认证,可以指定密码,也可以不指定密码在后续操作中输入密码:</p>
<pre><code class="language-bash">curl -u user:pwd http://man.linuxde.net
curl -u user http://man.linuxde.net

</code></pre>
<h3 id="13ftp">13、FTP</h3>
<h4 id="1列出ftp服务器上的目录列表">1)、列出ftp服务器上的目录列表</h4>
<pre><code class="language-bash">curl ftp://www.xxx.com/ --user name:passwd
curl ftp://www.xxx.com/ –u name:passwd #简洁写法
curl ftp://name:passwd@www.xxx.com #简洁写法2
</code></pre>
<p>例如:在IP地址192.168.43.117上搭建FTP服务器,并设置用户名为<code>user</code>,密码为<code>123456</code><br>
现在我们要显示服务器上根目录下的所有文件信息,命令如下:</p>
<pre><code class="language-bash">curl -u user:123456 ftp://192.168.43.117
</code></pre>
<p>执行结果如下:<br>
<img src="https://img-blog.csdnimg.cn/20200825175650353.png#pic_center"><br>
<strong>简洁写法:</strong></p>
<pre><code class="language-bash">curl ftp://user:123456@192.168.43.117
</code></pre>
<p>执行结果如下:<br>
<img src="https://img-blog.csdnimg.cn/20200825175927946.png#pic_center"></p>
<h4 id="2只列出目录不显示进度条">2)、只列出目录,不显示进度条</h4>
<pre><code class="language-bash">curl ftp://www.xxx.com –u name:passwd -s
</code></pre>
<h4 id="3下载一个文件">3)、下载一个文件:</h4>
<p><strong>格式</strong></p>
<pre><code class="language-bash">curl ftp://www.xxx.com/size.zip –u name:passwd -o size.zip
</code></pre>
<p>示例如下:<br>
从服务器的根目录下下载文件test.c,保存到本地,本地文件名也为test.c。<br>
【注意】如果没有-o选项,程序会吧数据流定向到stdout,即直接把文件内容显示到终端上。</p>
<pre><code class="language-bash">curl ftp://user:123456@192.168.43.117/test.c -o test.c
</code></pre>
<p>执行结果如下:<br>
<img src="https://img-blog.csdnimg.cn/20200825180137389.png#pic_center"><br>
<strong>简洁模式</strong></p>
<pre><code class="language-bash">curl -u user:123456 ftp://192.168.43.117/list.h -o list.h
</code></pre>
<p>执行结果如下:<br>
<img src="https://img-blog.csdnimg.cn/20200825180250268.png#pic_center"></p>
<h4 id="4上载一个文件">4)、上载一个文件:</h4>
<pre><code class="language-bash">curl –u name:passwd -T size.mp3 ftp://www.xxx.com/mp3/
</code></pre>
<p>举例如下:</p>
<pre><code class="language-bash">curl -u user:123456 ftp://192.168.43.117/ -T list.h
</code></pre>
<p><img src="https://img-blog.csdnimg.cn/20200825180711167.png#pic_center"><br>
可以看到文件并没有上传成功,返回错误码是25,参考第五章</p>
<pre><code class="language-bash">25        FTP couldn't STOR file. The server denied the STOR operation, used for FTP uploading.
</code></pre>
<p>可知,是因为服务器没有赋予存储的权限,所以设置服务器的write权限即可。</p>
<p><img src="https://img-blog.csdnimg.cn/2020082518100392.png#pic_center"></p>
<h4 id="5从服务器上删除文件使用curl传递ftp协议的dele命令">5)、从服务器上删除文件(使用curl传递ftp协议的DELE命令):</h4>
<pre><code class="language-bash">curl –u name:passwd ftp://www.xxx.com/ -X 'DELE mp3/size.mp3'
</code></pre>
<h4 id="6另外curl不支持递归下载不过可以用数组方式下载文件比如我们要下载1-10gif连续命名的文件">6)、另外curl不支持递归下载,不过可以用数组方式下载文件,比如我们要下载1-10.gif连续命名的文件:**</h4>
<pre><code class="language-bash">curl –u name:passwd ftp://www.xxx.com/img/.gif –O #O字母大写
</code></pre>
<h4 id="7要连续下载多个文件">7)、要连续下载多个文件:</h4>
<pre><code class="language-bash">curl –u name:passwd ftp://www.xxx.com/img/.jpg –O #O字母大写
</code></pre>
<h1 id="六实现日志文件定时上传">六、实现日志文件定时上传</h1>
<h2 id="功能">功能</h2>
<ol>
<li>程序运行时要记录当前日志文件的最后修改时间;</li>
<li>每个10秒钟就检查下log文件是否被修改,如果没有被修改就休眠10秒钟;</li>
<li>如果log文件被修改了,就将当前的日志文件拷贝成备份文件,备份文件名字加上当前时间;</li>
<li>通过curl发送给ftp服务器;</li>
<li>删除备份文件,重复步骤2。</li>
</ol>
<h3 id="程序流程图如下">程序流程图如下:</h3>
<p><img src="https://img-blog.csdnimg.cn/20200826160208560.png#pic_center"></p>
<h3 id="函数功能介绍">函数功能介绍</h3>
<h4 id="init">init()</h4>
<p>首先记录当前log文件时间,并记录到全局变量<code>last_mtime</code>中。</p>
<h4 id="check_file_change">check_file_change()</h4>
<p>读取文件最后修改时间,并和<code>last_mtime</code>进行比较,如果相同就返回0,不同就返回1.</p>
<h4 id="file_name_add_time">file_name_add_time()</h4>
<p>将当前的日志文件拷贝成备份文件,备份文件名字加上当前时间。</p>
<h4 id="stat">stat()​</h4>
<p>得到对应文件的属性信息,存放到struct stat结构体变量中。</p>
<h4 id="system">system()</h4>
<p>执行参数中字符串对应的命令</p>
<h3 id="代码如下">代码如下:</h3>
<pre><code class="language-c">/*   Copyright (C)   公众号: yikoulinux*/
#include &lt;sys/stat.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;unistd.h&gt;
#include &lt;time.h&gt;

typedef struct stat ST;
unsigned long last_mtime;

/*用户名密码暂时写死,实际应该保存在配置文件*/
char name="user";
char pass ="123456";
char ip   ="192.168.43.117";
char filename="t.log";
char dstfile={0};

int init(void)
{
        //准备结构体
        ST status;
       
        //调用stat函数
        int res = stat(filename,&amp;status);
        if(-1 == res)
        {
                perror("error:open file fail\n");
                return 0;
        }
        last_mtime = status.st_mtime;
        printf("init time:%s \n",ctime(&amp;last_mtime));
        return 1;
}
       
intcheck_file_change(void)
{
        //准备结构体
        ST status;
       
        //调用stat函数
        int res = stat(filename,&amp;status);
        if(-1 == res)
        {
                perror("error:open file fail\n");
                return 0;
        }
//        printf("old:%s new:%s",ctime(&amp;last_mtime),ctime(&amp;status.st_mtime));
        if(last_mtime == status.st_mtime)
        {
                printf("file not change\n");
                return 0;
        }else{
                printf("file updated\n");       
                last_mtime = status.st_mtime;
                return 1;
        }

}
void file_name_add_time(void)
{
        ST status;
        time_t t;        
        struct tm *tblock;       
        char cmd={0};
               
        t = time(NULL);
        tblock = localtime(&amp;t);
       
        sprintf(dstfile,"t-%d-%d-%d-%d-%d-%d.log",
                tblock-&gt;tm_year+1900,
                tblock-&gt;tm_mon,
                tblock-&gt;tm_mday,
                tblock-&gt;tm_hour,
                tblock-&gt;tm_min,
                tblock-&gt;tm_sec);
        sprintf(cmd,"cp %s %s",filename,dstfile);
//        printf("cdm=%s\n",cmd);
        system(cmd);
}
int main(void)
{

        char cmd={0};

        init();
        while(1)
        {       
                if(check_file_change() == 1)
                {
                        file_name_add_time();
                        sprintf(cmd,"curl -u %s:%s ftp://%s/ -T %s",name,pass,ip,dstfile);
        //                printf("cdm=%s\n",cmd);
                        system(cmd);
                        unlink(dstfile);
                }
                sleep(10);       
        }
}
</code></pre>
<h4 id="运行截图">运行截图:</h4>
<p><strong>第一步:</strong><br>
<img src="https://img-blog.csdnimg.cn/20200826161824656.png#pic_center"><br>
因为log文件没有被修改过,所以程序不会上传。</p>
<p><strong>第二步:</strong><br>
手动输入字符串 yikoulinux 到日志文件 t.log中。<br>
<img src="https://img-blog.csdnimg.cn/20200826161921208.png#pic_center">第三步:<br>
因为文件发生了改变,所以打印“file updated”,同时可以看到curl上传文件的log信息。<br>
<img src="https://img-blog.csdnimg.cn/20200826161944794.png#pic_center">以下是FTP服务器的根目录,可以看到,上传的日志文件:<code>t-2020-7-26-1-19-45.log</code>。<br>
<img src="https://img-blog.csdnimg.cn/20200826162007538.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Rhb2Nhb2thZmVp,size_16,color_FFFFFF,t_70#pic_center"></p>
<h2 id="补充">【补充】</h2>
<ol>
<li>配置信息,直接在代码中写死,通常应该从配置文件中读取,为方便读者阅读,本代码没有增加该功能;</li>
<li>FTP服务器搭建,本文没有说明,相关文件比较多,大家可以自行搜索,一口君用的是File zilla;<br>
<img src="https://img-blog.csdnimg.cn/20200826162608453.png#pic_center"></li>
<li>通常这种需要长时间运行的程序,需要设置成守护进程,本文没有添加相应功能,读者可以自行搜索。如果强烈要求可以单开一篇详细介绍。</li>
<li>代码中time的管理函数,请读者自行搜索相关文章。</li>
<li>curl也提供了相关的函数库curl.lib,如果要实现更灵活的功能可以使用对应的api。</li>
<li>之所以先把文件拷贝成备份文件,主要是考虑其他模块随时可能修改日志文件,起到一定保护作用。</li>
</ol>
<p>想和博主交流,请关注公众号「一口Linux」</p>


</div>
<div id="MySignature" role="contentinfo">
    欢迎关注公众号:一口Linux<br><br>
来源:https://www.cnblogs.com/yikoulinux/p/13569333.html
頁: [1]
查看完整版本: Linux命令cURL详解,并实现文件定时上传到ftp服务器的程序