`
xieye
  • 浏览: 835788 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

利用python的ftp客户端自动更新文件

阅读更多
问题的提出:

开发笔记本(windows),测试服务器(linux)都在办公室,远程服务器在远程(系统随便)。

原本使用svn更新代码,而且svn跨平台。开发机和测试机都安装了,但是远程不允许装任何程序,只有ftp帐号,别的神马都没有。

怎么更新代码呢?当然可以手动更新,但是程序员喜欢自动化。于是有如下python代码来实现自动化操作。

具体步骤,首先开发机修改代码,然后测试机更新,更新的同时需另外写程序(我用php)来把svn的更新记录搞到一张mysql的表里(其实文件也行),搞表里的操作是自动的。

然后测试机如果测试通过,需要部署到远程上,只需在测试机上执行python /.../.../svnupdate.py即可

目前的程序缺点:中文文件名和文件夹名貌似不支持

注意事项,
1、php程序和python程序都跑在测试机上,是linux,需要php和python和svn安装环境,并且php需要root身份或能执行system命令的身份,程序中执行了svn info等linux命令
2、假定程序在/www/code下,而ftp的服务端根路径是/www,所以需要把/www去掉再做ftp操作。


两张表,一张只放svn版本号,测试机每更新一次就自动记录最新版本号。
另一张记录svn的具体历史。
CREATE TABLE `svn_version` (
  `value` int(11) NOT NULL default 0 COMMENT 'svn当前版本'
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


CREATE TABLE `svn_history` (
  `id` int(11) NOT NULL auto_increment COMMENT '主键id',
  `author` varchar(255) NOT NULL default '' COMMENT '原作者',
  `operate` varchar(255) NOT NULL default '' COMMENT '操作,通常是A,M,D中的一个',
  `svn_version` int not null default 0 comment '版本号',
  `filename`    varchar(255) not null default '' comment '文件名或文件夹名',
  `created_at` int(11) NOT NULL default 0 COMMENT '创建时间',
   hasprocess int not null default 0 comment '是否处理过,默认未处理',
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;



python初哥的svnupdate.py代码如下
#-*- coding:utf-8 -*-

# 例:FTP编程 
#
# 功能统计
#  1)创建文件夹
#  2)添加文件
#  3)覆盖(修改文件) 注:就是添加,因为添加默认就是覆盖文件
#  4)删除文件
#  5)删除文件夹(级联删除)
# 
#  
#  
# 首先:测试客户机有个svn_history表,每次测试客户机更新时会把svn的记录加到表里 
#  
#  
from ftplib import FTP 
import re
import platform
import MySQLdb


def get_folder_arr(ftp, name, arr={}):
    ftp.cwd(name)
    list = ftp.nlst()
    for subname in list:
        new_name = join_name(name, subname)
        arr[new_name]={}
        if is_folder(subname):
            get_folder_arr(ftp, new_name, arr[new_name])
    return arr

def get_folder_arr_simple(ftp, name):
    arr=[]
    ftp.cwd(name)
    list = ftp.nlst()
    for subname in list:
        new_name = join_name(name, subname)
        arr.append(new_name)
    return arr

def get_folder_arr_simple_no_fullname(ftp, name):
    arr=[]
    ftp.cwd(name)
    list = ftp.nlst()
    for subname in list:
        arr.append(subname)
    return arr


def join_name(folder_name, file_name):
    return folder_name + '/' + file_name

def get_left_from_fullname(name):
    match = re.search("^(.+)/[^/]+$", name)
    return match.group(1)

def get_right_from_fullname(name):
    match = re.search("^.+/([^/]+)$", name)
    return match.group(1)
    

def is_folder_in_fullname(name):
    return is_folder(get_right_from_fullname(name))

def is_file_in_fullname(name):
    return is_file(get_right_from_fullname(name))


def is_folder(name):
    if len(name)==1: return True   
    if re.match("^.[^.]+$", name): # 除了开头,全部不带点的就是文件夹,还有1个字符我也认为是文件夹
        return True
    else:
        return False

def is_file(name):
    return not is_folder(name)

def is_empty_folder(ftp,name):
    ftp.cwd(name)
    list=ftp.nlst()
    if len(list) == 0:
        return True
    else:
        return False
    
# 删除文件夹的方法是,先清空里面全部(文件和文件夹),再删除本身    
def del_folder(ftp,name):
    arr = get_folder_arr_simple(ftp, name)
    # 现在开始递归
    for key in arr:
        if is_folder_in_fullname(key) : # 删文件夹
            del_folder(ftp, key)
        else:        # 否则删除文件
            file_name = get_right_from_fullname(key)
            folder_name  = get_left_from_fullname(key)
            ftp.cwd(folder_name)
            ftp.delete(file_name) 
    folder_name = get_right_from_fullname(name)
    parent_folder_name  = get_left_from_fullname(name)
    ftp.cwd(parent_folder_name)
    ftp.rmd(folder_name)             


def get_ftp():
    ftp = FTP() 
    port = 21 
    
    # 连接FTP服务器
    ftp.connect('www.example.net',port) 
    user = 'username'
    passwd = 'passwd'
    # 登录 
    ftp.login(user, passwd)
    return ftp

def cut_www(name):
    match = re.search("^/www(.+)$", name)
    return match.group(1)

# 公开接口,创建文件夹,参数类似/www/code/web/11,假设11是文件夹
def public_mkdir(ftp, dir_name):
    windows2003_name = cut_www(dir_name)
    try:
        ftp.mkd(windows2003_name)
    except:
        pass
    
    
def public_add_and_update_file(ftp, file_name):
    windows2003_name =  cut_www(file_name)
    try:
        ftp.cwd(get_left_from_fullname(windows2003_name))
        # 准备上传文件
        file_handler = open(file_name, 'rb')
        ftp.storbinary('STOR '+ get_right_from_fullname(windows2003_name), file_handler)
        file_handler.close()
    except:
        pass
 
 
def public_del_file_and_folder(ftp, name):
    windows2003_name =  cut_www(name)
    # 判断是否存在
    try:
        realname = get_right_from_fullname(windows2003_name)
        parent_folder = get_left_from_fullname(windows2003_name)
        arr = get_folder_arr_simple_no_fullname(ftp, parent_folder)
        if realname in arr:
            if is_file(realname):
                ftp.cwd(parent_folder)
                ftp.delete(realname)
            else:
                del_folder(ftp, windows2003_name)    
    except:
        pass

    

def query_by_sql(sql):
    conn  = MySQLdb.Connect ( \
        host = 'localhost', 
        user = 'root',
        passwd = '1', 
        db = 'www', 
        charset="utf8",
    )
    cursor = conn.cursor( cursorclass = MySQLdb.cursors.DictCursor )
    
    cursor.execute( sql )
    rows = cursor.fetchall()
    cursor.close()
    conn.close()
    return rows

def execute_by_sql(sql):
    conn  = MySQLdb.Connect ( \
        host = 'localhost', 
        user = 'root',
        passwd = '1', 
        db = 'www', 
        charset="utf8",
    )
    cursor = conn.cursor( cursorclass = MySQLdb.cursors.DictCursor )
   
    cursor.execute( sql )
    conn.commit()
    cursor.close()
    conn.close()


def main_program():
    ftp = get_ftp()
    # 打印欢迎信息 
    print ftp.getwelcome() 
    
    arr = query_by_sql("select * from svn_history where hasprocess=0 order by id asc")
    for row in arr:
        name = row['filename']
        operate = row['operate']
        print operate + ' ' + name
        if operate == 'A':
            if is_folder_in_fullname(name):
                public_mkdir(ftp, name)
            else:
                public_add_and_update_file(ftp, name)
        if operate == 'M':
            public_add_and_update_file(ftp, name)
        if operate == 'D':
            public_del_file_and_folder(ftp, name)
        execute_by_sql("update svn_history set hasprocess=1 where id =" + str(row['id']))                    
    ftp.quit() 
    # 退出FTP服务器

main_program()



自动化的加到表里的php代码是
<?php 
  
/**
 * 该php程序会查询svn,并得到最新版本号,然后存入到表svn_version里
 * 
 * 
 * 2010-11-26
 */

include('CommandPublic.php'); //这只是为了数据库查询等,关系不大

define('target', '/www/data/log/svnhistory.txt');

//这是svn的版本库在本机的拷贝路径
define('defined_dir', '/www/code');

/**
 * 获得版本号
 *
 * @return unknown
 */
function get_svn_version(){
    $target_log = '/www/data/log/svnlog.txt';
    $command = 'svn info /www/code/ > ' . $target_log;
    
    system($command);
    $command = "chmod 777 " . $target_log;
    system($command);
    
    $version = '';
    $arr = file($target_log);
    foreach ($arr as $value) {
        $value = preg_replace('/\n|\r\n/','',$value);
        if (preg_match('/^修订版:\d+$/', $value)) {
            $version = preg_replace('/^修订版:(\d+)$/','$1', $value);
            break;
        }
        
    }
    return intval($version);
}

/**
 * 对于每个版本,都要把里面的若干条记录插到数据库的表svn_history
 * 
 * 若干条的意思是一条或多条
 *
 * @param int $version
 */
function set_version($version) 
{
    $db = Sys::getdb();
    //首先获取信息
    $version = intval($version);
    $command ='svn log -v -r '. $version.' /www/code >  '.target;
    system($command);
    $arr = file(target);
    
    $line ='';
    //这个循环实际只为获取一句话
    //类似如下
    //r2525 | xieye | 2011-02-09 15:22:46 +0800 (三, 09  2月 2011) | 1 line
    foreach ($arr as $value) {
        if (preg_match('/^r\d+/', $value)) {
            $line = $value;
            break;
        }
    }
    
    $author =trim(preg_replace('/^.+\\|(.+)\\|.+\\|.+$/', '$1', $line));
    
    //现在获取文件修改历史
    foreach ($arr as $value) {
        $value = preg_replace('/\n|\r\n/','', $value);
        
        if (preg_match('/^\s+[A-Z]\s+.+$/s', $value)) {
            $operate = preg_replace('/^\s+([A-Z])\s+.+$/s', '$1', $value);
            $file = preg_replace('/^\s+[A-Z]\s+(.+)$/s', '$1', $value);
            $obj = new DatabaseObject_SvnHistory(); //用这个类意义不大,仅仅是插一条记录,也可以直接写sql
            $obj->svn_version =$version ;
            $obj->filename =defined_dir . $file;
            $obj->author =$author;
            $obj->created_at =get_current_time();
            $obj->hasprocess =0;
            $obj->operate =$operate;
            $obj->save();
        }
    }
}

/**
 * 获取一个固定时间
 *
 * @return int
 */
function get_current_time()
{
    static $time=null;
    if ($time==null) {
        $time=time();
    }
    return $time;
}

$db = Sys::getdb();

//首先取得老的版本号
$sql = "select value from  svn_version";
$old_version =  intval($db->fetchOne($sql));


$version = get_svn_version();
$sql = "update svn_version set value={$version} ";
$db->query($sql);


//如果相等就什么也不做。注意这些代码都跑在linux服务器上。
if ($version == $old_version) {
    exit;
}

//否则,就需要从老版本加1开始,一直做到最新的版本。
for ($i = $old_version +1; $i <= $version; $i++) {
    set_version($i);
}

echo "\n数据库里的svn版本已更新。\n";
?>


分享到:
评论

相关推荐

    使用Python编写的自动下载工具

    标题中的“使用Python编写的自动下载工具”表明这是一个利用Python编程语言开发的程序,它的主要功能是自动化地从服务器上下载文件。这个程序可能包含了网络请求、文件处理以及可能的版本控制逻辑,使得用户能够方便...

    python实现ftp下载备份

    FTP(File Transfer Protocol)是互联网上用于文件传输的标准协议,而利用Python实现FTP下载备份功能可以帮助我们自动化地从远程服务器获取数据,确保数据的安全与可访问性。本教程将详细介绍如何使用Python来实现这...

    ftplib开源ftp客户端

    本文将详细介绍ftplib库的功能、用法以及如何利用它来实现FTP客户端操作。 首先,ftplib是Python标准库的一部分,位于`ftplib`模块下,无需额外安装即可使用。它提供了丰富的类和函数,可以方便地执行FTP协议中的...

    毕设 FTP客户端设计

    8. **错误处理和异常恢复**:良好的FTP客户端应具备处理各种网络问题和服务器错误的能力,例如重试失败的传输,断线后自动恢复等。 在实际开发中,你可以选择使用现有的FTP库,如Python的`ftplib`,Java的`java.net...

    python编的FTP下载器

    综上所述,Python编的FTP下载器利用Python的网络编程能力,实现了FTP协议的客户端和服务端功能,提供了一种方便的文件下载解决方案。在理解和使用这个下载器时,需要熟悉FTP协议、Python编程以及网络安全相关的知识...

    ftp定时上传下载文件

    在某些业务场景中,自动化的FTP定时上传和下载文件功能显得尤为重要,例如备份、同步数据或发布更新等。下面我们将详细探讨如何实现这一功能。 首先,FTP定时上传下载通常涉及到以下几个关键技术点: 1. FTP客户端...

    pyinstaller+python3+FTP上传简易版本

    总的来说,这个项目展示了如何利用Python3和PyInstaller创建一个FTP服务器,并将其打包成独立的.exe文件,以便在不支持Python的环境下运行。同时,通过批处理文件自动化打包流程,提高了开发效率。对于初学者来说,...

    python+pyqt+软件远程自动检测升级新版本+FTP服务器

    总的来说,这个实例展示了如何利用Python和PyQt构建一个简单的软件自动升级系统,利用FTP服务器作为发布新版本的渠道。这种自动化升级机制对于持续迭代的软件产品来说非常有用,能确保用户始终使用到最新、最稳定的...

    python写的文件操作,telnet,ftp,excel,log日志等模块示例

    在提供的文件中,我们看到有针对这些领域的五个Python脚本:EasyFtp.py(FTP客户端)、EasyExcel.py(Excel数据操作)、EasyLogUtil.py(日志管理)、EasyTelnet.py(Telnet客户端)以及EasyOs.py(操作系统接口)。...

    ftp上传demo

    9. **FTP脚本与自动化**:对于频繁的FTP操作,可以编写FTP脚本(如使用bash、Perl、Python等编程语言)或利用FTP客户端的批处理功能,实现文件上传的自动化。 10. **错误处理与调试**:在FTP上传过程中可能会遇到...

    FTP.rar_file transfer_ftp_python

    `ftplib`提供了一系列类和方法,用于实现FTP客户端的功能。例如,我们可以创建一个`FTP`对象,然后通过`connect()`方法连接到FTP服务器: ```python import ftplib ftp = ftplib.FTP("ftp.example.com") ftp.login...

    autoupdate_基于FTP编写自动下载工具_mostlyyrp_

    标题中的"autoupdate_基于FTP编写自动下载工具_mostlyyrp_"暗示了这是一个关于创建自动更新机制的项目,利用FTP(文件传输协议)来实现软件的自动下载。这个工具可能用于确保用户总是运行的是软件的最新版本。下面将...

    DOS批处理ftp下载文件

    `ftp -i -s:%~f0`命令启动FTP客户端并读取批处理文件自身的剩余部分作为命令脚本。`goto :eof`跳转到文件末尾,结束FTP命令脚本。 `ftp_script`标签下的部分是FTP命令脚本,首先进行用户认证,切换到远程目录,然后...

    文件传输服务(可搜索文件)python.zip

    在Python中,文件I/O操作可以通过内置的`open`函数完成,而网络传输则可以利用`socket`模块的API。为了提高效率和可靠性,可能还会采用多线程或异步IO(如`asyncio`库)来并发处理多个客户端的请求。 总的来说,本...

    基于Python的网络传输文件功能的设计与实现.zip

    4. **FTP(File Transfer Protocol)**:虽然Python可以自定义实现文件传输,但也可以利用标准库`ftplib`来实现FTP协议,方便地上传和下载文件。FTP适合于需要权限验证和管理的场景。 5. **HTTP/HTTPS**:Python的`...

    FTP实时上传客户端【源码】

    FTP(File Transfer Protocol)是一种广泛使用的互联网协议,用于在不同网络之间传输文件。...通过分析和理解这些技术点,你可以深入学习FTP客户端的开发,了解如何构建一个高效且可靠的文件同步工具。

    ftp_ftp数据下载_

    2. **FTP客户端配置**:某些FTP客户端支持批处理或自动化任务,可以预设一系列操作,如登录、下载特定文件或目录,然后按设定的时间间隔执行。 3. **Web接口**:利用FTP API或Web服务,结合HTTP请求实现自动化下载,...

    Python语言实现FTP服务器的方法共2页.pdf.zi

    `ftplib`是Python标准库的一部分,提供了FTP客户端和服务器的实现。要创建FTP服务器,我们需要了解以下几个核心概念: 1. **FTP服务器的构建基础**:首先,我们需要理解FTP协议的基本工作原理,包括命令和响应的...

    python2.7实现FTP文件下载功能

    利用Python实现FTP文件下载功能,可以让用户通过编写脚本来自动下载FTP服务器上的文件。在本例中,我们将探讨如何使用Python 2.7版本来完成这项任务。 首先,Python标准库中包含了一个名为`ftplib`的模块,该模块...

    ftp文件上传下载

    在实际应用中,FTP客户端软件如FileZilla、WinSCP等可以帮助我们轻松完成文件的上传和下载。这些软件通常提供图形化的界面,使得操作更加直观。它们支持拖放功能,可以方便地管理本地和远程目录,同时提供断点续传、...

Global site tag (gtag.js) - Google Analytics