精华内容
下载资源
问答
  • MSYS2 是一组工具和库,为您提供易于使用的环境,用于构建、安装和运行本机 Windows 软件。 它由一个名为 mintty 的命令行终端、bash、git 和 subversion 等版本控制系统、tar 和 awk 等工具,甚至 autotools 等构建...
  • 域管理:windows server分发与分配软件

    万次阅读 2018-06-19 15:31:21
    分发:把某个软件分发给用户以后,用户下次在任意计算机登录时,所部属的软件都会出现在用户计算机的“添加和删除程序”对话框中,供用户下载安装。用户配置>分配:分配是强制性的软件部属方式。当软件分配给...

    域管理:windows server分发与分配软件

    1.分发与分配

    用户配置>分发:把某个软件分发给用户以后,用户下次在任意计算机登录时,所部属的软件都会出现在用户计算机的“添加和删除程序”对话框中,供用户下载安装。

    用户配置>分配:分配是强制性的软件部属方式。当软件分配给用户时,用户无论在任意的计算机上登录的时,该软件都会自动安装,都可以在“开始”菜单或者是桌面上看到该软件的快捷方式。

    计算机配置,也可以选择分配和分发,当软件分配给计算机时,计算机在下一次启动的时候会自动下载并安装软件。

    2.在windows server2008上分配和分发软件

    1)环境

    (1)两台虚拟机:虚拟机1是windows server2008(域控机),虚拟机2是windows7。

    (2)在域控制器cy.com域下创建部门“财务部”,创建安全组“财务”,创建域用户caiwu001并且加入安全组。参考资料见 域的基本管理:创建部门和用户

    2)过程记录

    (1)在域控制器上创建一个共享目录Share,把要推送的软件放在这里,我下载了一个python2.7,它本来就是msi格式,省去了封装的步骤。这是因为windows系统分发软件只支持msi格式,我们平时用的exe格式必须通过一些软件将其封装为msi格式,这样才可以使用。

    (2)依次点击“开始”>“管理工具”>“组策略管理”,选择财务部,鼠标右键单击“在这个域中创建GPO并在此处链接”,在弹出的界面里随便命名,这里是“安装软件”。


    (3)选择“安装软件”,鼠标右键单击选择“编辑”会打开“组策略管理编辑器”窗口,在这里可以选择计算机配置还是用户配置。我选择了“用户配置”>“策略”>“软件设置”>“软件安装”。

    (4)选择“软件安装”,右键单击选择“属性”,软件安装属性选择我们共享文件夹的路径,其余配置根据需求选择。


    (5)选择“软件安装”,右键单击选择“新建”>“数据包”,选择数据包的路径。

    (6)我们已经完成了软件分配。

    注意:(1)封装exe软件为msi格式之后,可以先测试一下msi格式的软件是否可用。

    (2)共享文件夹的属性设置,共享和安全权限需要根据需求设置,为了方便测试,我这里设置的是everyone都有读取权限。

    3)测试

    在另一台虚拟机win7上登陆,使用我们创建的域用户“caiwu001”登陆,在开始菜单可以看到python2.7已经安装了。






    展开全文
  • MSYS2是工具和库的集合,为您提供了一个易于使用的环境,用于构建,安装和运行本机Windows软件。 它由一个名为mintty,bash,版本控制系统(如git和subversion),诸如tar和awk之类的工具,甚至是诸如autotools之类...
  • windows server 2008 R2软件分发

    千次阅读 2013-07-29 14:20:23
    1.建立共享隐藏文件夹,然后分配共享权限和NTFS权限,并将要分发的软件包放到此文件夹中。 2.打开组策略------计算机配置--------策略----------软件设置...3.然后选择新建数据包,选择要分发软件名称,点打开即可。

     

    1.建立共享隐藏文件夹,然后分配共享权限和NTFS权限,并将要分发的软件包放到此文件夹中。

    2.打开组策略------计算机配置--------策略----------软件设置----------软件安装属性,选择安装包的路径,然后确定。

    3.然后选择新建数据包,选择要分发的软件名称,点打开即可。

     

     

    展开全文
  • windows之间分发文件

    千次阅读 2017-10-11 19:41:05
    分布式压力机使用的是linux系统或或者是windows再或者是两者混用linux机器之间cp文件有很多种,而且都很方便,不需要额外装软件,预装的就能实现文件拷贝比如scp、ftp等都能实现 windows之间就比较麻烦了,os中可能...

    背景

    性能测试,使用分布式压力机进行规模较大的压测时,环境准备阶段需要将测试依赖的文件(测试数据文件、依赖jar包、依赖第三方程序等)拷贝到各个机器上
    分布式压力机使用的是linux系统或或者是windows再或者是两者混用

    linux机器之间cp文件有很多种,而且都很方便,不需要额外装软件,预装的就能实现文件拷贝比如scp、ftp等都能实现
    windows之间就比较麻烦了,os中可能都没有启用ftp,也没有开足够的共享权限等。也有可能你完全配置好一台windows,制作模版,再装其他机器。(别抬杠,不排除这种方法)

    使用ftp共享实现

    不是我要介绍的重点,自己问问度娘,网上很大篇幅是介绍这种方式的(略)

    文件中转实现分发

    我倾向拿来主义,所以我借助第三的程序。废话少说来干的

    准备

    服务器准备

    准备一台linux服务器:hostLinux
    准备N台windows服务:hostWin1……hostWinN

    软件准备

    pscp和psexec
    用法见附录或者去官网

    需求

    将hostWin1上的文件cp到hostWin2……hostWinN

    实现

    pscp能进行win与linux之间cp文件类似linux下的scp;
    psexec可以在windows之间远程执行命令,更重要的是有一个-c参数,可以将执行的命令拷贝到远程机器上执行,这样要拷贝文件的机器就不需要提前将命令准备好(在这里是pscp命令,也就是hostWin2……hostWinN上不需要做任何准备)

    检查linux和个windows之间的ping,windows之间的ping

    连通性检查可选,最好还是检查一下

    将待分发的文件上传至hostLinux上的指定目录

    pscp -pw hostLinuxPasswd [-r] localFile root@hostLinux:/root/transFile/

    在hostWin1上控制在hostWin2……hostWinN上执行pscp命令

    psexec -u hostWin2user -p hostWin2passwd -c -f pscp -pw xxxxx [-r] root@hostLinux:/root/transFile/ localFile 
    
    重复上面的动作

    验证hostWin2……hostWinN上文件的完整性

    传完了验证文件的完整性(验证一遍比较放心),可以通过远程执命令统计文件的个数,大小,md5等

    改进

    服务器很多,敲上面的命令是不是很糟心,虽然省略了打个各个终端操作,这么多命令也很累,写脚本,自动生成命令

    将win服务器列表写成配置文件

    #ip::user::passwd
    #x.x.x.x::yueling::yuelingp
    x.x.x.x::yueling::yuelingp
    x.x.x.x::yueling::yuelingp

    将linux服务器列表写成配置文件

    #ip::user::passwd
    #x.x.x.x::yueling::yuelingp
    x.x.x.x::yueling::yuelingp
    #当文件比较多或者比较大时,可以配置多个linux服务器作为中转,减轻一台服务器的网络和io压力(自己把握)

    将操作的文件写成配置文件

    #type::path
    #file
    f::c:\wmsFile\a.txt
    #folder
    D::c:\wmsFile

    文件存储的位置写成配置文件(这个一般不会用到)

    比如使用常用的性能测试工具LR加载测试依赖jar包或者文件,多个机器上的文件位置肯定是固定,否则脚本就会报错,Jmeter依赖文件、参数化文件等也是一样的

    核心代码

    读取配置文件

    package com.yueling.utils;
    
    import(略)
    
    /** 
    * @ClassName: ReadCfgFile 
    * @Description: TODO
    * @author yueling 
    * @date 2017年9月27日 下午2:45:26 
    *  
    */
    public class ReadCfgFile {
        private final static Logger logger = LoggerFactory.getLogger(ReadCfgFile.class);
    
        /** 
        * @Title: readTxt 
        * @Description: 读取配置文件,将结果放入arrayList对象中
        * @param @param filePath
        * @param @return
        * @return ArrayList<String>
        * @throws 
        */
        public static ArrayList<String> readTxt(String filePath) {
            ArrayList<String> arrayList = new ArrayList<String>();
            try {
                File file = new File(filePath);
                if (file.isFile() && file.exists()) {
                    InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "utf-8");
                    BufferedReader br = new BufferedReader(isr);
                    String lineTxt = null;
                    while ((lineTxt = br.readLine()) != null) {
                        if (lineTxt.trim().startsWith("#") || lineTxt.trim().equals("")) {
                            logger.info("忽略{}", lineTxt);
                        } else {
                            logger.info(lineTxt);
                            arrayList.add(lineTxt);
                        }
                    }
                    br.close();
                    isr.close();
                } else {
                    System.out.println("!");
                    logger.error("【{}】文件不存在", filePath);
                }
            } catch (Exception e) {
                logger.error("打开文件异常!");
            } finally {
            }
            return arrayList;
        }
    
        /** 
        * @Title: processServerList 
        * @Description: 处理服务器列表,将异常剔除
        * @param @return
        * @return ArrayList<ServerListObject>
        * @throws 
        */
        public static ArrayList<ServerListObject> processServerList(String filePath) {
    
            ArrayList<ServerListObject> serverList = new ArrayList<ServerListObject>();
    
    
            ArrayList<String> arrServerList = readTxt(filePath);
            String pattern = ".*::.*::.*";
            String[] tmp = null;
            for (int serverIndex = 0; serverIndex < arrServerList.size(); serverIndex++) {
                ServerListObject serverListObject = new ServerListObject();
                String serverInfo = arrServerList.get(serverIndex);
                boolean isMatch = Pattern.matches(pattern, serverInfo);
                if (isMatch) {
                    logger.info(serverInfo);
                    tmp = serverInfo.split("::");
                    int lenght = tmp.length;
                    if (lenght != 3) {
                        logger.error("格式不正确!【{}】正确格式为【ip::user::passwd】", serverInfo);
                    } else {
                        serverListObject.setIp(tmp[0]);
                        serverListObject.setUser(tmp[1]);
                        serverListObject.setPasswd(tmp[2]);
                        serverList.add(serverListObject);
                    }
                } else {
                    logger.error("格式不正确!【{}】正确格式为【ip::user::passwd】", serverInfo);
                }
            }
            return serverList;
        }
    
        /** 
        * @Title: processFileList 
        * @Description: 处理文件列表,将异常的剔除
        * @param @return
        * @return ArrayList<FileListObject>
        * @throws 
        */
        public static ArrayList<FileListObject> processFileList(String filePath) {
            ArrayList<FileListObject> fileList = new ArrayList<FileListObject>();
    
    
            ArrayList<String> arrFileList = readTxt(filePath);
            String pattern = ".*::.*";
            String[] tmp = null;
            for (int fileIndex = 0; fileIndex < arrFileList.size(); fileIndex++) {
                FileListObject fileListObject = new FileListObject();
                String fileInfo = arrFileList.get(fileIndex);
                boolean isMatch = Pattern.matches(pattern, fileInfo);
                if (isMatch) {
                    logger.info(fileInfo);
    
                    tmp = fileInfo.split("::");
                    int lenght = tmp.length;
                    if (lenght != 2) {
                        logger.error("格式不正确!【{}】正确格式为【type::path】", fileInfo);
                    } else {
                        // 处理文件是否存在
                        if (tmp[0].toUpperCase().equals("f".toUpperCase())) {
                            if (isFileExists(new File(tmp[1]))) {
                                fileListObject.setType(tmp[0]);
                                fileListObject.setPath(tmp[1]);
                                fileList.add(fileListObject);
                            }
                        } else if (tmp[0].toUpperCase().equals("d".toUpperCase())) {
                            if (isDirExists(new File(tmp[1]))) {
                                fileListObject.setType(tmp[0]);
                                fileListObject.setPath(tmp[1]);
                                fileList.add(fileListObject);
                            }
                        }
    
                    }
                } else {
                    logger.error("格式不正确!【{}】正确格式为【type:path】", fileInfo);
                }
            }
            return fileList;
        }
    
    
        /** 
        * @Title: isFileExists 
        * @Description: 判断文件是否存在
        * @param @param file
        * @param @return
        * @return boolean
        * @throws 
        */
        public static boolean isFileExists(File file) {
            boolean isExistsOrNotFlag = false;
            if (file.exists()) {
                logger.info("{} file exists", file);
                isExistsOrNotFlag = true;
            } else {
                logger.info("{} file not exists", file);
                isExistsOrNotFlag = false;
            }
            return isExistsOrNotFlag;
        }
    
    
        /** 
        * @Title: isDirExists 
        * @Description: 判断文件夹是否存在
        * @param @param file
        * @param @return
        * @return boolean
        * @throws 
        */
        public static boolean isDirExists(File file) {
    
            boolean isExistsOrNotFlag = false;
            if (file.exists()) {
                if (file.isDirectory()) {
                    logger.info("{} dir exists", file);
                    isExistsOrNotFlag = true;
                } else {
                    logger.info("{} the same name file exists, is not a dir", file);
                    isExistsOrNotFlag = false;
                }
            } else {
                logger.info("{} is not exists", file);
                isExistsOrNotFlag = false;
            }
            return isExistsOrNotFlag;
        }
    
    }

    组装命令执行

    通过上面的读取文件已经将合法的配置放入到相应的数组中,遍历组装命令即可(略)
    取一段检查服务器连通性的代码为例

    public static boolean winPingWinServer(ServerListObject serverListObject) {
            boolean serverAlive = false;
            Runtime rt = Runtime.getRuntime();
            Process process;
            // ping的返回中有ttl标识,通过指定的次数判断
            String contains = "TTL";
            int pingCount = 0;
    
            try {
                process = rt.exec("cmd.exe /c ping -n 2 " + serverListObject.getIp());
                pingCount = PrintResponseOnConsole.print(process, contains);
                if (pingCount == 2) {
                    serverAlive = true;
                    logger.info("localhost ping {} is alive",serverListObject.getIp());
                }else{
                    logger.info("localhost ping {} is not alive",serverListObject.getIp());
                }
            } catch (IOException e) {
                logger.error("localhost ping {} exception",serverListObject.getIp());
                e.printStackTrace();
            }
    
            return serverAlive;
        }

    使用system执行命令

    使用参数控制

    比如一部分命令没有必要重新执行,比如从本地上传到linux服务器,只需做一次,所以用参数控制

    public static void main(String[] args) {
            if (args.length == 0) {
                System.out.println("至少需要一个参数");
                System.out.println("参数需为:<init|upload|download>");
            } else {
                try {
                    filePath = directory.getCanonicalPath() + "\\config\\serverList.properties";
                } catch (IOException e) {
                    e.printStackTrace();
                }
                processServerList = ReadCfgFile.processServerList(filePath);
                try {
                    filePath = directory.getCanonicalPath() + "\\config\\puppetServer.properties";
                } catch (IOException e) {
                    e.printStackTrace();
                }
                processPuppetServerList = ReadCfgFile.processServerList(filePath);
    
                try {
                    filePath = directory.getCanonicalPath() + "\\config\\FileList.properties";
                } catch (IOException e) {
                    e.printStackTrace();
                }
                processFileList = ReadCfgFile.processFileList(filePath);
    
    
                try {
                    filePath = directory.getCanonicalPath() + "\\config\\output.bat";
                } catch (IOException e) {
                    e.printStackTrace();
                }
                // 根据传参决定执行那些功能
                if (args[0].toUpperCase().equals("init".toUpperCase())) {
                    // 检查服务器部分的测试
                    //testInit(directory, filePath, processServerList, processPuppetServerList, processFileList);
                    //testCountFiles(processServerList, processPuppetServerList);
                    //testRmFiles(processPuppetServerList);
                    testInitTxt(directory, filePath, processServerList, processPuppetServerList, processFileList);
                } else if (args[0].toUpperCase().equals("upload".toUpperCase())) {
                    // 测试上传文件
                    testValidUploadFileToPuppetServer(directory, filePath, processServerList, processPuppetServerList,
                            processFileList);
                } else if (args[0].toUpperCase().equals("download".toUpperCase())) {
                    // 测试下载文件到各个windows服务器
                    testValidDownloadFileFromPuppetServer(directory, filePath, processServerList, processPuppetServerList,
                            processFileList);
                } else {
                    System.out.println("参数需为:<init|upload|download>");
                }
            }
        }

    打包执行

    C:\Users\yueling.DANGDANG\Desktop>java -jar distribute.jar
    至少需要一个参数
    参数需为:<init|upload|download>
    
    C:\Users\yueling.DANGDANG\Desktop>

    附录

    pscp:
    PuTTY Secure Copy client
    Release 0.62
    Usage: pscp [options] [user@]host:source target
           pscp [options] source [source...] [user@]host:target
           pscp [options] -ls [user@]host:filespec
    Options:
      -V        print version information and exit
      -pgpfp    print PGP key fingerprints and exit
      -p        preserve file attributes
      -q        quiet, don't show statistics
      -r        copy directories recursively
      -v        show verbose messages
      -load sessname  Load settings from saved session
      -P port   connect to specified port
      -l user   connect with specified username
      -pw passw login with specified password
      -1 -2     force use of particular SSH protocol version
      -4 -6     force use of IPv4 or IPv6
      -C        enable compression
      -i key    private key file for authentication
      -noagent  disable use of Pageant
      -agent    enable use of Pageant
      -batch    disable all interactive prompts
      -unsafe   allow server-side wildcards (DANGEROUS)
      -sftp     force use of SFTP protocol
      -scp      force use of SCP protocol
    PsExec v1.97 - Execute processes remotely
    Copyright (C) 2001-2009 Mark Russinovich
    Sysinternals - www.sysinternals.com
    
    PsExec executes a program on a remote system, where remotely executed console
    applications execute interactively.
    
    Usage: psexec [\\computer[,computer2[,...] | @file]][-u user [-p psswd][-n s][-l][-s|-e][-x][-i [session]][-c [-f|-v]][-w directory][-d][-<priority>][-a n,n,...] cmd [arguments]
         -a         Separate processors on which the application can run with
                    commas where 1 is the lowest numbered CPU. For example,
                    to run the application on CPU 2 and CPU 4, enter:
                    "-a 2,4"
         -c         Copy the specified program to the remote system for
                    execution. If you omit this option the application
                    must be in the system path on the remote system.
         -d         Don't wait for process to terminate (non-interactive).
         -e         Does not load the specified account's profile.
         -f         Copy the specified program even if the file already
                    exists on the remote system.
         -i         Run the program so that it interacts with the desktop of the
                    specified session on the remote system. If no session is
                    specified the process runs in the console session.
         -h         If the target system is Vista or higher, has the process
                    run with the account's elevated token, if available.
         -l         Run process as limited user (strips the Administrators group
                    and allows only privileges assigned to the Users group).
                    On Windows Vista the process runs with Low Integrity.
         -n         Specifies timeout in seconds connecting to remote computers.
         -p         Specifies optional password for user name. If you omit this
                    you will be prompted to enter a hidden password.
         -s         Run the remote process in the System account.
         -u         Specifies optional user name for login to remote
                    computer.
         -v         Copy the specified file only if it has a higher version number
                    or is newer on than the one on the remote system.
         -w         Set the working directory of the process (relative to
                    remote computer).
         -x         Display the UI on the Winlogon secure desktop (local system
                    only).
         -priority  Specifies -low, -belownormal, -abovenormal, -high or
                    -realtime to run the process at a different priority. Use
                    -background to run at low memory and I/O priority on Vista.
         computer   Direct PsExec to run the application on the remote
                    computer or computers specified. If you omit the computer
                    name PsExec runs the application on the local system,
                    and if you specify a wildcard (\\*), PsExec runs the
                    command on all computers in the current domain.
         @file      PsExec will execute the command on each of the computers listed
                    in the file.
         program    Name of application to execute.
         arguments  Arguments to pass (note that file paths must be
                    absolute paths on the target system).

    原文链接 http://blog.csdn.net/yue530tomtom/article/details/78207506

    展开全文
  • Socket文件分发工具

    2017-11-27 13:49:18
    1.读取本地文件列表快速复制分发到多台远程服务器上(并行发布) 2.可视化管理系统分发配置 3.可全量或部分备份远程服务器文件列表 4.可还原指定远程服务器到任意已备份的系统版本 5.可停止,重启远程IIS站点及...
  • Python打包分发工具setuptools

    万次阅读 多人点赞 2018-07-01 14:14:48
    分发工具 setuptools 第一个安装文件 使用安装文件创建 wheel Source distribution Built distribution Wheel 安装 Wheel 上传 Wheel 到 PyPI 注册 PyPI 账号 安装 twine 使用 twine 上传 setup() 参数 name ...

    本文主要介绍如何把个人编写的 Python 应用打包并上传到官方仓库 PyPI,使得可以直接通过 pip 进行安装使用,并在 PyPI 上进行维护。

    分发工具 setuptools

    曾经 Python 的分发工具是 distutils,但它无法定义包之间的依赖关系。setuptools 则是它的增强版,能帮助我们更好的创建和分发 Python 包,尤其是具有复杂依赖关系的包。其通过添加一个基本的依赖系统以及许多相关功能,弥补了该缺陷。他还提供了自动包查询程序,用来自动获取包之间的依赖关系,并完成这些包的安装,大大降低了安装各种包的难度,使之更加方便。

    一般 Python 安装会自带 setuptools,如果没有可以使用 pip 安装:

    $ pip install setuptools
    

    setuptools 简单易用,只需写一个简短的 setup.py 安装文件,就可以将你的 Python 应用打包。


    第一个安装文件

    在目录 learn_setup 下新建安装文件 setup.py,然后创建包 myapp 模拟要打包源码包:

    .
    ├── myapp
    │ └── __init__.py
    └── setup.py
    

    一个最简单的 setup.py 文件内容如下:

    from setuptools import setup
    
    setup(
        name='firstApp', # 应用名
        version='0.0.1', # 版本号
        packages=['myapp'], # 包括在安装包内的 Python 包
    )

    使用安装文件创建 wheel

    有了上面的 setup.py 文件,我们就可以打出各种安装包,主要分为两类:sdist 和 bdist。

    Source distribution

    使用 sdist 可以打包成 source distribution,支持的压缩格式有:

    FormatDescriptionNotes
    zipzip file (.zip)Windows 默认
    gztargzip’ed tar file (.tar.gz)Unix 默认
    bztarbzip2’ed tar file (.tar.bz2)
    xztarxz’ed tar file (.tar.xz)
    ztarcompressed tar file (.tar.Z)
    tartar file (.tar)

    使用方式为:

    $ python setup.py sdist --formats=gztar,zip
    

    现在目录下多出 dist 和 *.egg-info 目录,dist 内保存了我们打好的包,上面命令使用 --formats 指定了打出 .tar.gz.zip 包,如果不指定则如上表根据具体平台默认格式打包。

    包的名称为 setup.py 中定义的 name, version以及指定的包格式,格式如:firstApp-0.0.1.tar.gz。

    Built distribution

    使用 bdist 可以打出 built distribution,和源码包相比,由于预先构建好,所以安装更快:

    FormatDescriptionNotes
    gztargzipped tar file (.tar.gz)Unix 默认
    bztarbzipped tar file (.tar.bz2)
    xztarxzipped tar file (.tar.xz)
    ztarcompressed tar file (.tar.Z)
    tartar file (.tar)
    zipzip file (.zip)Windows 默认
    rpmRPM
    pkgtoolSolaris pkgtool
    sduxHP-UX swinstall
    wininstself-extracting ZIP file for Windows
    msiMicrosoft Installer.

    使用上,和 sdist 一样,可以使用 --formats 指定包格式。如:

    $ python setup.py bdist --formats=rpm
    

    同时为了简化操作,setuptools 提供了如下命令:

    CommandFormatsNotes
    bdist_dumbtar, gztar, bztar, xztar, ztar, zipWindows 默认 zip, Unix 默认 gztar
    bdist_rpmrpm, srpm
    bdist_wininstwininst
    bdist_msimsi

    所以上面打 rpm 包可以使用:

    $ python setup.py bdist_rpm
    

    如果使用 bdist_wininst,打出来的是 exe 安装文件,可以点击安装。

    Wheel

    Wheel 也是一种 built 包,而且是官方推荐的打包方式。也许你曾经遇见或使用过 egg 包,但现在 wheel 是官方推荐的打包方式(https://wheel.readthedocs.io/en/stable/)。

    wheel 包的优点:

    • Faster installation for pure Python and native C extension packages.
    • Avoids arbitrary code execution for installation. (Avoids setup.py)
    • Installation of a C extension does not require a compiler on Windows or macOS.
    • Allows better caching for testing and continuous integration.
    • Creates .pyc files as part of installation to ensure they match the Python interpreter used.
    • More consistent installs across platforms and machines.

    使用 wheel 打包,首先要安装 wheel:

    $ pip install wheel
    

    然后使用 bdist_wheel 打包:

    $ python setup.py bdist_wheel
    

    执行成功后,目录下除了 dist 和 *.egg-info 目录外,还有一个 build 目录用于存储打包中间数据。

    wheel 包的名称如 firstApp-0.0.1-py3-none-any.whl,其中 py3 指明只支持 Python3。

    可以使用参数 --universal,包名如 mfirstApp-0.0.1-py2.py3-none-any.whl,表明 wheel 包同时支持 Python2 和 Python3

    使用 universal 也成为通用 wheel 包,反之称为纯 wheel 包。


    安装 Wheel

    上一节的示例应用没有任何内容。下面添加模块 greet 并重新打包。

    # greet.py
    
    def hello():
        print('Hello, welcome to setuptools!')

    使用 bdist_wheel 再次打包后,我们可以使用 pip 安装到本地 Python 的 site-packages 目录。

    $ pip install dist/fisrtApp-0.0.1-py3-none-any.whl
    

    现在和其他使用 pip 安装的三方库一样使用:

    from myapp.greet import hello
    
    hello()

    应用开发过程中会频繁变更,每次安装都需要先卸载旧版本很麻烦。使用 develop 开发模式安装的话,实际代码不会拷贝到 site-packages 下,而是除一个指向当前应用的链接(*.egg-link)。这样当前位置的源码改动就会马上反映到 site-packages。使用如下:

    $ pip install -e .  # 或者 python setup.py develop
    

    如需卸载,使用 pip uninstall


    上传 Wheel 到 PyPI

    Wheel 包可以自己使用和传输给其他人使用,但是维护更新不方便,而 PyPI 作为 Python 的 软件仓库,让所有人可以方便的上传和下载,以及管理三方库。

    注册 PyPI 账号

    登录 https://pypi.python.org/pypi,进入 Register 注册账号。

    安装 twine

    虽然 setuptools 支持使用 setup.py upload 上传包文件到 PyPI,但只支持 HTTP 而被新的 twine 取代。

    同样的,需要先安装 twine:

    $ pip install twine
    

    使用 twine 上传

    使用 upload:

    $ twine upload dist/*
    

    输入 username 和 password 即上传至 PyPI。如果不想每次输入账号密码,可以在家目录下创建 .pypirc 文件,内容如下:

    [distutils]
    index-servers =
        pypi
        pypitest
    
    [pypi]
    username: 
    password: 
    
    [pypitest]
    repository: https://test.pypi.org/legacy/
    username: 
    password: 
    

    填上自己的账号密码即可,这里配置了官方的 pypi 和 pypitest,若要配置其他仓库,按格式添加。

    回到 PyPI 主页即可看到上传的 firstApp。

    这里写图片描述

    这里写图片描述

    PyPI 主页显示会有延迟,所以不能马上搜索到结果,pip search 也可能搜索不到,但已经可以使用 pip 安装。

    以上就是 Python 打包和分发的全部内容,当然是最简单的功能。更复杂的打包,比如模块过滤,非 py 文件打包,作者信息等常见的需求,都被实现在 setup() 内。所以接下来详细介绍 setup()。


    setup() 参数

    这里写图片描述

    这里写图片描述

    上面的 setup.py 安装文件内,我们已经使用了 setup() 一些参数:name, version, packages。

    name

    项目名,也是最终在 PyPI 上搜索的名称。

    name = 'firstApp'
    

    version

    项目版本号,一般由三部分组成:MAJOR, MINOR, MAINTENANCE。
    - MAJOR version when they make incompatible API changes,
    - MINOR version when they add functionality in a backwards-compatible manner, and
    - MAINTENANCE version when they make backwards-compatible bug fixes.

    版本号的选择参见:https://packaging.python.org/tutorials/distributing-packages/#choosing-a-versioning-scheme

    version='0.0.1'
    

    packages

    列出项目内需要被打包的所有 package。一般使用 setuptools.find_packages() 自动发现。

    packages=find_packages(exclude=['contrib', 'docs', 'tests*'])
    

    exclude 用于排除不打包的 package。

    description

    项目的简短描述,一般一句话就好,会显示在 PyPI 上名字下端。

    description='My first Python project'
    

    对项目的完整描述,使用 long_description。如果此字符串是 rst 格式的,PyPI 会自动渲染成 HTML 显示。也可指定使用 markdown。

    long_description=long_description,
    long_description_content_type='text/x-rst'
    

    url

    通常为 GitHub上 的链接或者 readthedocs 的链接。。

    url='https://github.com/pypa/sampleproject'
    

    author

    作者信息。

    author='example',
    author_email='example@example.com'
    

    license

    项目许可证。

    license='MIT'
    

    关于各种许可证的介绍和选择,参考:https://choosealicense.com/

    classifiers

    项目分类,完整可选项参考:https://pypi.python.org/pypi?%3Aaction=list_classifiers

    classifiers=[
        # How mature is this project? Common values are
        # 3 - Alpha
        # 4 - Beta
        # 5 - Production/Stable
        'Development Status :: 3 - Alpha',
    
        # Indicate who your project is intended for
        'Intended Audience :: Developers',
        'Topic :: Software Development :: Build Tools',
    
        # Pick your license as you wish (should match "license" above)
         'License :: OSI Approved :: MIT License',
    
        # Specify the Python versions you support here. In particular, ensure
        # that you indicate whether you support Python 2, Python 3 or both.
        'Programming Language :: Python :: 2',
        'Programming Language :: Python :: 2.6',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.2',
        'Programming Language :: Python :: 3.3',
        'Programming Language :: Python :: 3.4',
    ],
    

    keywords

    项目关键词列表。

    keywords='sample setuptools development'
    

    project_urls

    项目相关额外连接,如代码仓库,文档地址等。

    project_urls={
        'Documentation': 'https://packaging.python.org/tutorials/distributing-packages/',
        'Funding': 'https://donate.pypi.org',
        'Say Thanks!': 'http://saythanks.io/to/example',
        'Source': 'https://github.com/pypa/sampleproject/',
        'Tracker': 'https://github.com/pypa/sampleproject/issues',
    }
    

    install_requires

    项目依赖的 Python 库,使用 pip 安装本项目时会自动检查和安装依赖。

    install_requires=['pyyaml']
    

    依赖的安装参考:https://packaging.python.org/discussions/install-requires-vs-requirements/#install-requires-vs-requirements-files

    python_requires

    指定项目依赖的 Python 版本。

    python_requires='>=3'
    

    package_data

    项目依赖数据文件,数据文件必须放在项目目录内且使用相对路径。

    package_data={
        'myapp': ['data/*.yml'],
    }
    

    如果不指定作为目录的键为空串,则代表对所有模块操作(下例中将包含所有包内 data 目录下的 yaml 文件):

    package_data={
        '': ['data/*.yml'],
    }
    

    data_files

    如果数据文件存在于项目外,则可以使用 data_files 参数或者 MANIFEST.in 文件进行管理。

    • 如果用于源码包,则使用 MANIFEST.in;
    • 如果用于 wheel,则使用 data_files。

      data_files=[(‘mydata’, [‘data/conf.yml’])]

    上述设置将在打包 wheel 时,将 data/conf.yml 文件添加至 mydata 目录。

    data_files 不能使用路径通配符。

    此外,scripts, py_modeles, entry_points, console_scripts 等参数参考:https://packaging.python.org/tutorials/distributing-packages/#setup-args


    其他初始化文件

    在阅读 Github 上的 Python 库时,除了最基本核心的 setup.py 文件和主程序之外,还会看到其他一些文件。本节将介绍它们的作用和使用方法。

    setup.cfg

    包含了构建时候的一些默认参数,如:

    [bdist_wheel]
    
    universal=1
    

    用于在使用 bdist_wheel 的时候的默认设置 --universal 参数 。

    README.rst/README.md

    项目说明文档,使用 reStrutruedText 可以在 PyPI 上很好的渲染,但 Markdown 则支持不够好。

    MANIFEST.in

    此文件在打源码包的时候告诉 setuptools 还需要额外打包哪些文件。

    # Include the README
    include *.md
    
    # Include the license file
    include LICENSE.txt
    
    # Include the data files
    recursive-include data *
    

    不同于 data_files,MANIFEST.in 支持路径通配符。

    LICENSE.txt

    项目许可说明文件。


    setuptools 默认打包的文件

    • README.rst/README.md
    • setup.cfg
    • MANIFEST.in

    所以其他的文件,如 LICENSE.txt,在源码包时需要手动在 MANIFEST.in 里添加 include,在 wheel 包时需要在 setup.cfg 添加:

    [metadata]
    license_file = LICENSE.txt
    

    PyPI 上传推荐配置

    • setup.py
      • name
      • version
      • author
      • author_email
      • url
      • packages
      • description
      • package_data/data_files
    • setup.cfg
    • MANIFEST.in
    • README.rst
    • LICENSE.txt
    • <项目>

    一个完整的 setup.py 示例

    from setuptools import setup, find_packages
    
    with open('README.rst', 'r', encoding='utf-8') as rd:
        long_description = rd.read()
    
    setup(
        name="HelloWorld",
        version="0.1",
        packages=find_packages(),
        scripts=['say_hello.py'],
    
        # Project uses reStructuredText, so ensure that the docutils get
        # installed or upgraded on the target machine
        install_requires=['docutils>=0.3'],
    
        package_data={
            # If any package contains *.txt or *.rst files, include them:
            '': ['*.txt', '*.rst'],
            # And include any *.msg files found in the 'hello' package, too:
            'hello': ['*.msg'],
        },
    
        # metadata for upload to PyPI
        author="Me",
        author_email="me@example.com",
        description="This is an Example Package",
        long_description = long_description,
        license="PSF",
        keywords="hello world example examples",
        url="http://example.com/HelloWorld/", # project home page, if any
        project_urls={
            "Bug Tracker": "https://bugs.example.com/HelloWorld/",
            "Documentation": "https://docs.example.com/HelloWorld/",
            "Source Code": "https://code.example.com/HelloWorld/",
        }
    
        # could also include long_description, download_url, classifiers, etc.
    )

    1. https://packaging.python.org/tutorials/distributing-packages/
    2. https://setuptools.readthedocs.io/en/latest/setuptools.html#developer-s-guide
    3. https://pythonwheels.com/
    4. https://github.com/pypa/twine
    展开全文
  • 安装和维护软件对于我们从事IT行业的人来说是常有的事,也是一件特别耗时的事。现在技术的不断发展也同时带动着软件的频繁更新,为了适应公司作业的需求,我们也只能随着潮流将软件卸了又装,装了又卸。一两台机如果...
  • 在需要给大量客户端部署软件时,使用组策略的软件分发功能还是很有效率的。比如前面文章中谈到的部署limitlogin工具,需要在客户端安装电脑上安装软件的客户端,如果手动安装需要耗费很多时间,效率也很低。如果使用...
  • 进入服务器系统中,以windowsserver 2012 R2 为例: 一、安装域控制器 打开服务器管理器,点击管理,添加角色和功能。 进入配置,选择基于角色或基于功能的安装,单击下一步。 从服务器池中选择服务器,单击下...
  • 利用组策略软件分发部署MSI程序包

    千次阅读 2017-11-07 22:19:00
    利用组策略软件分发部署MSI程序包 在局域网中,我们都会面临要给...那么我们今天就讲一下如何能过Windows Server 3003的组策略实现软件分发。 一、软件分发所支持的软件类型 二、发布和指派应用程序(Publis...
  • 巧用Windows Server 2003分发功能

    千次阅读 2005-06-02 23:33:00
    如果你也是一名网管,那么你不妨通过本文来感受一下软件分发功能带来的神奇“减负”魅力。简单地说,分发功能就是将软件分布发送到工作站的功能。以往,很多网络管理员都采用共享的方法,但共享所引起的安全隐患往往...
  • 分发 Windows Media 组件 发布日期: 12/14/2004 | 更新日期: 12/14/2004 Microsoft New Media Platforms Division 摘要 本文说明了将 Microsoft® Windows Media® ru
  • 域控制器服务器上实现软件分发

    千次阅读 2012-04-12 18:06:13
     假设现在要将ty.server域中的“Windows Server 2003管理工具包”程序“qq2009.msi”分发到所有的工作站上,那么则应进行以下设置。 提示:分发软件必须是MSI封装文件,如果想将非MSI格式的文件封装成MSI文件,...
  • http://www.360doc.com/showweb/0/0/37986.aspxhttp://news.onlinedown.net/info/17874-1.htm 开源软件新时代 55个经典开源Windows工具 55个经典开源Windows工具
  • 开源软件新时代:55个经典开源Windows工具作者 feiy, 星期五 6 一月 2006 à 15:04 :: 飞扬的天空 :: #165 :: rss Tags:Free , Software  开 放源代码软件已经成为一个时髦的名词,这里有两个有力的证据:...
  • 组策略--分发软件

    千次阅读 2007-06-20 14:43:00
    如果你也是一名网管,那么你不妨通过本文来感受一下软件分发功能带来的神奇“减负”魅力。简单地说,分发功能就是将软件分布发送到工作站的功能。以往,很多网络管理员都采用共享的方法,但共享所引起的安全隐患往往...
  • Windows 2000 资源工具工具对于管理任务察看本文应用于的产品function loadTOCNode(){}注意:这篇文章是由无人工介入的自动的机器翻译系统翻译完成。这些文章是微软为不懂英语的用户提供的, 以使他们能够理解这些...
  • 关于2016版Administudio如何把exe安装程序转换成msi(第一次发,有描述不正确的见谅)
  • 此存储库托管A2J文档组装工具(DAT)的可分发生产版本。 文档组装工具是一个可选软件,用于在访谈结束时生成pdf文档。 它要求A2Jviewer,wkhtmltopdf和nodejs 12+才能正常运行。 Windows推荐的其他工具是nvm和iis...
  • WannaRen勒索病毒背后,一条恶意软件分发产业链 原创 威胁对抗能力部 [绿盟科技安全情报](javascript:void(0)???? 今天 通告编号:NS-2020-0024 2020-04-08 TA****G: WannaRen、勒索软件、kms 版本: 1.0 ...
  • 比如不只只是要分发一个酷狗软件,还要分发其他软件,如Office 这时就需要在C:\softshare下建立子文件夹C:\softshare\Office来存放Office的文件 我这里只是分发一个酷狗软件 所以只建立了一个文件夹 3.。使用管理...
  • Windows EXE打包工具Inno Setup

    千次阅读 2019-08-12 11:15:51
    Inno Setup 是一个免费的 Windows 安装程序制作软件。第一次发表是在 1997 年,Inno Setup 今天在功能设置和稳定性上的竞争力可能已经超过一些商业的安装程序制作软件。Inno Setup支持自2006年以来的每个Windows版本...
  • 域用组策略分发软件时exe转.MSI

    热门讨论 2009-11-25 17:07:49
    域用组策略分发软件时,只能分发.MSI 这个软件转化速度非常快
  • win10安装appx工具Microsoft’s new Universal Windows Platform applications use the .Appx or .AppxBundle file format. They’re normally installed from the Windows Store, but Windows 10 allows you to ...
  • windows/Linux网络工具

    千次阅读 2010-08-11 08:54:00
    在2000 和2003年非常成功的推出了安全工具调查后,Insecure.Org 非常高兴为大家带来2006年度的安全工具调查。我-Fyodor对nmap-hackers 邮件列表中的用户进行了调查,让大家来分享他们最喜欢用的工具,结果有3243名...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 34,749
精华内容 13,899
关键字:

windows软件分发工具