分类: 技术

  • Linux tar.gz、tar、bz2、zip 等解压缩、压缩命令详解

    Linux tar.gz、tar、bz2、zip 等解压缩、压缩命令详解

    分类 编程技术

    Linux 常用的压缩与解压缩命令有:tar、gzip、gunzip、bzip2、bunzip2、compress 、uncompress、 zip、 unzip、rar、unrar 等。


    tar

    参数:

    • -z 用gzip指令处理备份文件
    • -v 显示执行过程
    • -f 指定备份文件
    • -c 建立备份文件
    • -t 列出备份文件的内容
    • -x 从备份文件中还原文件
    • -p 保留权限
    • –exclude 排除指定文件

    最常用的打包命令是 tar,使用 tar 程序打出来的包我们常称为 tar 包,tar 包文件的命令通常都是以 .tar 结尾的。生成 tar 包后,就可以用其它的程序来进行压缩了,所以首先就来讲讲 tar 命令的基本用法。

    tar 命令的选项有很多(用 man tar 可以查看到),但常用的就那么几个选项,下面来举例说明一下:

    # tar -cf all.tar *.jpg

    这条命令是将所有 .jpg 的文件打成一个名为 all.tar 的包。-c 是表示产生新的包,-f 指定包的文件名。

    # tar -rf all.tar *.gif

    这条命令是将所有 .gif 的文件增加到 all.tar 的包里面去,-r 是表示增加文件的意思。

    # tar -uf all.tar logo.gif

    这条命令是更新原来 tar 包 all.tar 中 logo.gif 文件,-u 是表示更新文件的意思。

    # tar -tf all.tar

    这条命令是列出 all.tar 包中所有文件,-t 是列出文件的意思。

    # tar -xf all.tar

    这条命令是解出 all.tar 包中所有文件,-x 是解开的意思。

    以上就是 tar 的最基本的用法。为了方便用户在打包解包的同时可以压缩或解压文件,tar 提供了一种特殊的功能。这就是 tar 可以在打包或解包的同时调用其它的压缩程序,比如调用 gzip、bzip2 等。

    1) tar调用

    gzip 是 GNU 组织开发的一个压缩程序,.gz 结尾的文件就是 gzip 压缩的结果。与 gzip 相对的解压程序是 gunzip。tar 中使用 -z 这个参数来调用gzip。下面来举例说明一下:

    # tar -czf all.tar.gz *.jpg

    这条命令是将所有 .jpg 的文件打成一个 tar 包,并且将其用 gzip 压缩,生成一个 gzip 压缩过的包,包名为 all.tar.gz。

    # tar -xzf all.tar.gz

    这条命令是将上面产生的包解开。

    2) tar 调用 bzip2

    bzip2 是一个压缩能力更强的压缩程序,.bz2 结尾的文件就是 bzip2 压缩的结果。

    与 bzip2 相对的解压程序是 bunzip2。tar 中使用 -j 这个参数来调用 gzip。下面来举例说明一下:

    # tar -cjf all.tar.bz2 *.jpg

    这条命令是将所有 .jpg 的文件打成一个 tar 包,并且将其用 bzip2 压缩,生成一个 bzip2 压缩过的包,包名为 all.tar.bz2

    # tar -xjf all.tar.bz2

    这条命令是将上面产生的包解开。

    3)tar 调用 compress

    compress 也是一个压缩程序,但是好象使用 compress 的人不如 gzip 和 bzip2 的人多。.Z 结尾的文件就是 bzip2 压缩的结果。与 compress 相对的解压程序是 uncompress。tar 中使用 -Z 这个参数来调用 compress。下面来举例说明一下:

    # tar -cZf all.tar.Z *.jpg

    这条命令是将所有 .jpg 的文件打成一个 tar 包,并且将其用 compress 压缩,生成一个 uncompress 压缩过的包,包名为 all.tar.Z。

    # tar -xZf all.tar.Z

    这条命令是将上面产生的包解开。

    有了上面的知识,你应该可以解开多种压缩文件了,下面对于 tar 系列的压缩文件作一个小结:

    1) 对于.tar结尾的文件

    tar -xf all.tar

    2) 对于 .gz 结尾的文件

    gzip -d all.gz
    gunzip all.gz

    3)对于 .tgz 或 .tar.gz 结尾的文件

    tar -xzf all.tar.gz
    tar -xzf all.tgz

    4) 对于 .bz2 结尾的文件

    bzip2 -d all.bz2
    bunzip2 all.bz2

    5) 对于 tar.bz2 结尾的文件

    tar -xjf all.tar.bz2

    6) 对于 .Z 结尾的文件

    uncompress all.Z

    7) 对于 .tar.Z 结尾的文件

    tar -xZf all.tar.z

    另外对于 Windows 下的常见压缩文件 .zip 和 .rar,Linux 也有相应的方法来解压它们:

    1) 对于 .zip

    linux 下提供了 zip 和 unzip 程序,zip 是压缩程序,unzip 是解压程序。它们的参数选项很多,这里只做简单介绍,依旧举例说明一下其用法:

    # zip all.zip *.jpg

    这条命令是将所有 .jpg 的文件压缩成一个 zip 包:

    # unzip all.zip

    这条命令是将 all.zip 中的所有文件解压出来。

    2) 对于 .rar

    要在 linux 下处理 .rar 文件,需要安装 RAR for Linux。下载地址:http://www.rarsoft.com/download.htm,下载后安装即可。

    # tar -xzpvf rarlinux-x64-5.6.b5.tar.gz
    # cd rar 
    # make

    这样就安装好了,安装后就有了 rar 和 unrar 这两个程序,rar 是压缩程序,unrar 是解压程序。它们的参数选项很多,这里只做简单介绍,依旧举例说明一下其用法:

    # rar a all *.jpg

    这条命令是将所有 .jpg 的文件压缩成一个 rar 包,名为 all.rar,该程序会将 .rar 扩展名将自动附加到包名后。

    # unrar e all.rar

    这条命令是将 all.rar 中的所有文件解压出来:


    扩展内容

    tar

    -c: 建立压缩档案 
    -x:解压 
    -t:查看内容 
    -r:向压缩归档文件末尾追加文件 
    -u:更新原压缩包中的文件

    这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个。下面的参数是根据需要在压缩或解压档案时可选的。

    -z:有gzip属性的 
    -j:有bz2属性的 
    -Z:有compress属性的 
    -v:显示所有过程 
    -O:将文件解开到标准输出 

    下面的参数 -f 是必须的:

    -f: 使用档案名字,切记,这个参数是最后一个参数,后面只能接档案名。 

    # tar -cf all.tar *.jpg

    这条命令是将所有 .jpg 的文件打成一个名为 all.tar 的包。-c 是表示产生新的包,-f 指定包的文件名。

    # tar -rf all.tar *.gif 

    这条命令是将所有 .gif 的文件增加到 all.tar 的包里面去。-r 是表示增加文件的意思。

    # tar -uf all.tar logo.gif 

    这条命令是更新原来 tar 包 all.tar 中 logo.gif 文件,-u 是表示更新文件的意思。

    # tar -tf all.tar 

    这条命令是列出 all.tar 包中所有文件,-t 是列出文件的意思。

    # tar -xf all.tar 

    这条命令是解出 all.tar 包中所有文件,-x 是解开的意思。

    压缩

    tar –cvf jpg.tar *.jpg       // 将目录里所有jpg文件打包成 tar.jpg 
    tar –czf jpg.tar.gz *.jpg    // 将目录里所有jpg文件打包成 jpg.tar 后,并且将其用 gzip 压缩,生成一个 gzip 压缩过的包,命名为 jpg.tar.gz 
    tar –cjf jpg.tar.bz2 *.jpg   // 将目录里所有jpg文件打包成 jpg.tar 后,并且将其用 bzip2 压缩,生成一个 bzip2 压缩过的包,命名为jpg.tar.bz2 
    tar –cZf jpg.tar.Z *.jpg     // 将目录里所有 jpg 文件打包成 jpg.tar 后,并且将其用 compress 压缩,生成一个 umcompress 压缩过的包,命名为jpg.tar.Z 
    rar a jpg.rar *.jpg          // rar格式的压缩,需要先下载 rar for linux 
    zip jpg.zip *.jpg            // zip格式的压缩,需要先下载 zip for linux

    解压

    tar –xvf file.tar         // 解压 tar 包 
    tar -xzvf file.tar.gz     // 解压 tar.gz 
    tar -xjvf file.tar.bz2    // 解压 tar.bz2 
    tar –xZvf file.tar.Z      // 解压 tar.Z 
    unrar e file.rar          // 解压 rar 
    unzip file.zip            // 解压 zip 

    总结

    1、*.tar 用 tar –xvf 解压 
    2、*.gz 用 gzip -d或者gunzip 解压 
    3、*.tar.gz和*.tgz 用 tar –xzf 解压 
    4、*.bz2 用 bzip2 -d或者用bunzip2 解压 
    5、*.tar.bz2用tar –xjf 解压 
    6、*.Z 用 uncompress 解压 
    7、*.tar.Z 用tar –xZf 解压 
    8、*.rar 用 unrar e解压 
    9、*.zip 用 unzip 解压
  • 进程管理工具Supervisor使用教程

    Supervisor 是 Linux/Unix 系统下的一个进程管理工具。可以很方便的监听、启动、停止和重启一个或多个进程。通过 Supervisor 管理的进程,当进程意外被 Kill 时,Supervisor 会自动将它重启,可以很方便地做到进程自动恢复的目的,而无需自己编写 shell 脚本来管理进程。

    安装 Supervisor

    这里仅举例 CentOS 系统下的安装方式:

    # 安装 epel 源,如果此前安装过,此步骤跳过
    yum install -y epel-release
    yum install -y supervisor  

    创建一个配置文件

    cp /etc/supervisord.conf /etc/supervisord.d/supervisord.conf

    编辑新复制出来的配置文件 /etc/supervisord.d/supervisord.conf,并在文件结尾处添加以下内容后保存文件:

    # 新建一个应用并设置一个名称,这里设置为 hyperf
    [program:hyperf]
    # 设置命令在指定的目录内执行 
    directory=/var/www/hyperf/ 
    # 这里为您要管理的项目的启动命令 
    command=php ./bin/hyperf.php start 
    # 以哪个用户来运行该进程 
    user=root 
    # supervisor 启动时自动该应用 
    autostart=true 
    # 进程退出后自动重启进程 
    autorestart=true 
    # 进程持续运行多久才认为是启动成功 
    startsecs=1 
    # 重试次数 startretries=3 
    # stderr 日志输出位置 
    stderr_logfile=/var/www/hyperf/runtime/stderr.log 
    # stdout 日志输出位置 
    stdout_logfile=/var/www/hyperf/runtime/stdout.log

    建议同时增大配置文件中的 minfds 配置项,默认为 1024。同时也应该修改系统的 unlimit,防止出现 Failed to open stream: Too many open files 的问题。

    启动 Supervisor

    运行下面的命令基于配置文件启动 Supervisor 程序:

    supervisord -c /etc/supervisord.d/supervisord.conf

    使用 supervisorctl 管理项目

    # 启动 hyperf 应用
    supervisorctl start hyperf
    # 重启 hyperf 应用
    supervisorctl restart hyperf
    # 停止 hyperf 应用
    supervisorctl stop hyperf  
    # 查看所有被管理项目运行状态
    supervisorctl status
    # 重新加载配置文件
    supervisorctl update
    # 重新启动所有程序
    supervisorctl reload
  • 道设计模式面试题总结(含答案解析和思维导图)

    Q1:设计模式有哪些原则?

    开闭原则:OOP 中最基础的原则,指一个软件实体(类、模块、方法等)应该对扩展开放,对修改关闭。强调用抽象构建框架,用实现扩展细节,提高代码的可复用性和可维护性。

    单一职责原则:一个类、接口或方法只负责一个职责,降低代码复杂度以及变更引起的风险。

    依赖倒置原则:程序应该依赖于抽象类或接口,而不是具体的实现类。

    接口隔离原则:将不同功能定义在不同接口中实现接口隔离,避免了类依赖它不需要的接口,减少了接口之间依赖的冗余性和复杂性。

    里氏替换原则:开闭原则的补充,规定了任何父类可以出现的地方子类都一定可以出现,可以约束继承泛滥,加强程序健壮性。

    迪米特原则:也叫最少知道原则,每个模块对其他模块都要尽可能少地了解和依赖,降低代码耦合度。

    合成/聚合原则:尽量使用组合(has-a)/聚合(contains-a)而不是继承(is-a)达到软件复用的目的,避免滥用继承带来的方法污染和方法爆炸,方法污染指父类的行为通过继承传递给子类,但子类并不具备执行此行为的能力;方法爆炸指继承树不断扩大,底层类拥有的方法过于繁杂,导致很容易选择错误。


    Q2:设计模式的分类,你知道哪些设计模式?

    创建型: 在创建对象的同时隐藏创建逻辑,不使用 new 直接实例化对象,程序在判断需要创建哪些对象时更灵活。包括工厂/抽象工厂/单例/建造者/原型模式。

    结构型: 通过类和接口间的继承和引用实现创建复杂结构的对象。包括适配器/桥接模式/过滤器/组合/装饰器/外观/享元/代理模式。

    行为型: 通过类之间不同通信方式实现不同行为。包括责任链/命名/解释器/迭代器/中介者/备忘录/观察者/状态/策略/模板/访问者模式。


    Q3:说一说简单工厂模式

    简单工厂模式指由一个工厂对象来创建实例,客户端不需要关注创建逻辑,只需提供传入工厂的参数。

    适用于工厂类负责创建对象较少的情况,缺点是如果要增加新产品,就需要修改工厂类的判断逻辑,违背开闭原则,且产品多的话会使工厂类比较复杂。

    Calendar 抽象类的 getInstance 方法,调用 createCalendar 方法根据不同的地区参数创建不同的日历对象。

    Spring 中的 BeanFactory 使用简单工厂模式,根据传入一个唯一的标识来获得 Bean 对象。


    Q4:说一说工厂方法模式

    工厂方法模式指定义一个创建对象的接口,让接口的实现类决定创建哪种对象,让类的实例化推迟到子类中进行。

    客户端只需关心对应工厂而无需关心创建细节,主要解决了产品扩展的问题,在简单工厂模式中如果产品种类变多,工厂的职责会越来越多,不便于维护。

    Collection 接口这个抽象工厂中定义了一个抽象的 iterator 工厂方法,返回一个 Iterator 类的抽象产品。该方法通过 ArrayList 、HashMap 等具体工厂实现,返回 Itr、KeyIterator 等具体产品。

    Spring 的 FactoryBean 接口的 getObject 方法也是工厂方法。


    Q5:抽象工厂模式了解吗?

    抽象工厂模式指提供一个创建一系列相关或相互依赖对象的接口,无需指定它们的具体类。

    客户端不依赖于产品类实例如何被创建和实现的细节,主要用于系统的产品有多于一个的产品族,而系统只消费其中某一个产品族产品的情况。抽象工厂模式的缺点是不方便扩展产品族,并且增加了系统的抽象性和理解难度。

    java.sql.Connection 接口就是一个抽象工厂,其中包括很多抽象产品如 Statement、Blob、Savepoint 等。


    Q6:单例模式的特点是什么?

    单例模式属于创建型模式,一个单例类在任何情况下都只存在一个实例,构造方法必须是私有的、由自己创建一个静态变量存储实例,对外提供一个静态公有方法获取实例。

    优点是内存中只有一个实例,减少了开销,尤其是频繁创建和销毁实例的情况下并且可以避免对资源的多重占用。缺点是没有抽象层,难以扩展,与单一职责原则冲突。

    Spring 的 ApplicationContext 创建的 Bean 实例都是单例对象,还有 ServletContext、数据库连接池等也都是单例模式。

    Q7:单例模式有哪些实现?

    饿汉式:在类加载时就初始化创建单例对象,线程安全,但不管是否使用都创建对象可能会浪费内存。

    public class HungrySingleton {
        private HungrySingleton(){}
    
        private static HungrySingleton instance = new HungrySingleton();
    
        public static HungrySingleton getInstance() {
            return instance;
        }
    }

    懒汉式:在外部调用时才会加载,线程不安全,可以加锁保证线程安全但效率低。

    public class LazySingleton {
        private LazySingleton(){}
    
        private static LazySingleton instance;
    
        public static LazySingleton getInstance() {
            if(instance == null) {
                instance = new LazySingleton();
            }
            return instance;
        }
    }

    双重检查锁:使用 volatile 以及多重检查来减小锁范围,提升效率。

    public class DoubleCheckSingleton {
        private DoubleCheckSingleton(){}
    
        private volatile static DoubleCheckSingleton instance;
    
        public static DoubleCheckSingleton getInstance() {
            if(instance == null) {
                synchronized (DoubleCheckSingleton.class) {
                    if (instance == null) {
                        instance = new DoubleCheckSingleton();
                    }
                }
            }
            return instance;
        }
    }

    静态内部类:同时解决饿汉式的内存浪费问题和懒汉式的线程安全问题。

    public class StaticSingleton {
        private StaticSingleton(){}
    
        public static StaticSingleton getInstance() {
            return StaticClass.instance;
        }
    
        private static class StaticClass {
            private static final StaticSingleton instance = new StaticSingleton();
        }
    }

    枚举:《Effective Java》提倡的方式,不仅能避免线程安全问题,还能防止反序列化重新创建新的对象,绝对防止多次实例化,也能防止反射破解单例的问题。

    public enum EnumSingleton {
        INSTANCE;
    }

    Q8:讲一讲代理模式

    代理模式属于结构型模式,为其他对象提供一种代理以控制对这个对象的访问。优点是可以增强目标对象的功能,降低代码耦合度,扩展性好。缺点是在客户端和目标对象之间增加代理对象会导致请求处理速度变慢,增加系统复杂度。

    Spring 利用动态代理实现 AOP,如果 Bean 实现了接口就使用 JDK 代理,否则使用 CGLib 代理。

    静态代理:代理对象持有被代理对象的引用,调用代理对象方法时也会调用被代理对象的方法,但是会在被代理对象方法的前后增加其他逻辑。需要手动完成,在程序运行前就已经存在代理类的字节码文件,代理类和被代理类的关系在运行前就已经确定了。 缺点是一个代理类只能为一个目标服务,如果要服务多种类型会增加工作量。

    动态代理:动态代理在程序运行时通过反射创建具体的代理类,代理类和被代理类的关系在运行前是不确定的。动态代理的适用性更强,主要分为 JDK 动态代理和 CGLib 动态代理。

    • JDK 动态代理:通过 Proxy 类的 newInstance 方法获取一个动态代理对象,需要传入三个参数,被代理对象的类加载器、被代理对象实现的接口,以及一个 InvocationHandler 调用处理器来指明具体的逻辑,相比静态代理的优势是接口中声明的所有方法都被转移到 InvocationHandler 的 invoke 方法集中处理。
    • CGLib 动态代理:JDK 动态代理要求实现被代理对象的接口,而 CGLib 要求继承被代理对象,如果一个类是 final 类则不能使用 CGLib 代理。两种代理都在运行期生成字节码,JDK 动态代理直接写字节码,而 CGLib 动态代理使用 ASM 框架写字节码,ASM 的目的是生成、转换和分析以字节数组表示的已编译 Java 类。 JDK 动态代理调用代理方法通过反射机制实现,而 GCLib 动态代理通过 FastClass 机制直接调用方法,它为代理类和被代理类各生成一个类,该类为代理类和被代理类的方法分配一个 int 参数,调用方法时可以直接定位,因此调用效率更高。

    Q9:讲一讲装饰器模式

    装饰器模式属于结构型模式,在不改变原有对象的基础上将功能附加到对象,相比继承可以更加灵活地扩展原有对象的功能。

    装饰器模式适合的场景:在不想增加很多子类的前提下扩展一个类的功能。

    java.io 包中,InputStream 字节输入流通过装饰器 BufferedInputStream 增强为缓冲字节输入流。


    Q10:装饰器模式和动态代理的区别?

    装饰器模式的关注点在于给对象动态添加方法,而动态代理更注重对象的访问控制。动态代理通常会在代理类中创建被代理对象的实例,而装饰器模式会将装饰者作为构造方法的参数。


    Q11:讲一讲适配器模式

    适配器模式属于结构型模式,它作为两个不兼容接口之间的桥梁,结合了两个独立接口的功能,将一个类的接口转换成另外一个接口使得原本由于接口不兼容而不能一起工作的类可以一起工作。

    缺点是过多使用适配器会让系统非常混乱,不易整体把握。

    java.io 包中,InputStream 字节输入流通过适配器 InputStreamReader 转换为 Reader 字符输入流。

    Spring MVC 中的 HandlerAdapter,由于 handler 有很多种形式,包括 Controller、HttpRequestHandler、Servlet 等,但调用方式又是确定的,因此需要适配器来进行处理,根据适配规则调用 handle 方法。

    Arrays.asList 方法,将数组转换为对应的集合(注意不能使用修改集合的方法,因为返回的 ArrayList 是 Arrays 的一个内部类)。


    Q12:适配器模式和和装饰器模式以及代理模式的区别?

    适配器模式没有层级关系,适配器和被适配者没有必然连续,满足 has-a 的关系,解决不兼容的问题,是一种后置考虑。

    装饰器模式具有层级关系,装饰器与被装饰者实现同一个接口,满足 is-a 的关系,注重覆盖和扩展,是一种前置考虑。

    适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。


    Q13:讲一讲策略模式

    策略模式属于行为型模式,定义了一系列算法并封装起来,之间可以互相替换。策略模式主要解决在有多种算法相似的情况下,使用 if/else 所带来的难以维护。

    优点是算法可以自由切换,可以避免使用多重条件判断并且扩展性良好,缺点是策略类会增多并且所有策略类都需要对外暴露。

    在集合框架中,经常需要通过构造方法传入一个比较器 Comparator 进行比较排序。Comparator 就是一个抽象策略,一个类通过实现该接口并重写 compare 方法成为具体策略类。

    创建线程池时,需要传入拒绝策略,当创建新线程使当前运行的线程数超过 maximumPoolSize 时会使用相应的拒绝策略处理。


    Q14:讲一讲模板模式

    模板模式属于行为型模式,使子类可以在不改变算法结构的情况下重新定义算法的某些步骤,适用于抽取子类重复代码到公共父类。

    优点是可以封装固定不变的部分,扩展可变的部分。缺点是每一个不同实现都需要一个子类维护,会增加类的数量。

    为防止恶意操作,一般模板方法都以 final 修饰。

    HttpServlet 定义了一套处理 HTTP 请求的模板,service 方法为模板方法,定义了处理HTTP请求的基本流程,doXXX 等方法为基本方法,根据请求方法的类型做相应的处理,子类可重写这些方法。


    Q15:讲一讲观察者模式

    观察者模式属于行为型模式,也叫发布订阅模式,定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。主要解决一个对象状态改变给其他对象通知的问题,缺点是如果被观察者对象有很多的直接和间接观察者的话通知很耗时, 如果存在循环依赖的话可能导致系统崩溃,另外观察者无法知道目标对象具体是怎么发生变化的。

    ServletContextListener 能够监听 ServletContext 对象的生命周期,实际上就是监听 Web 应用。当 Servlet 容器启动 Web 应用时调用 contextInitialized 方法,终止时调用 contextDestroyed 方法。

  • 切换github账号后,push时403错误

    如果你在多个github账户之间切换,并在不同的github上克隆了仓库时,那么在提交代码的时候就会容易出现403错误,如下:

    image

    这个错误信息其实很明显,就是你要提交的github和你当前的github不是一个账号,我在网上搜索一下,也有很多种解决办法,下面介绍其中一种,亲测有效:
    打开终端输入:

    rundll32.exe keymgr.dll,KRShowKeyMgr
    

    在弹出的框中选择github并编辑

    image

    在下拉框中选择需要的账户,输入密码,点击确定

    image
    再重新push就可以成功了。

  • rsync 用法教程

    一、简介

    rsync 是一个常用的 Linux 应用程序,用于文件同步。

    它可以在本地计算机与远程计算机之间,或者两个本地目录之间同步文件(但不支持两台远程计算机之间的同步)。它也可以当作文件复制工具,替代cpmv命令。

    它名称里面的r指的是 remote,rsync 其实就是”远程同步”(remote sync)的意思。与其他文件传输工具(如 FTP 或 scp)不同,rsync 的最大特点是会检查发送方和接收方已有的文件,仅传输有变动的部分(默认规则是文件大小或修改时间有变动)。

    二、安装

    如果本机或者远程计算机没有安装 rsync,可以用下面的命令安装。

    
    # Debian
    $ sudo apt-get install rsync
    
    # Red Hat
    $ sudo yum install rsync
    
    # Arch Linux
    $ sudo pacman -S rsync
    

    注意,传输的双方都必须安装 rsync。

    三、基本用法

    3.1 -r 参数

    本机使用 rsync 命令时,可以作为cpmv命令的替代方法,将源目录同步到目标目录。

    
    $ rsync -r source destination
    

    上面命令中,-r表示递归,即包含子目录。注意,-r是必须的,否则 rsync 运行不会成功。source目录表示源目录,destination表示目标目录。

    如果有多个文件或目录需要同步,可以写成下面这样。

    
    $ rsync -r source1 source2 destination
    

    上面命令中,source1source2都会被同步到destination目录。

    3.2 -a 参数

    -a参数可以替代-r,除了可以递归同步以外,还可以同步元信息(比如修改时间、权限等)。由于 rsync 默认使用文件大小和修改时间决定文件是否需要更新,所以-a-r更有用。下面的用法才是常见的写法。

    
    $ rsync -a source destination
    

    目标目录destination如果不存在,rsync 会自动创建。执行上面的命令后,源目录source被完整地复制到了目标目录destination下面,即形成了destination/source的目录结构。

    如果只想同步源目录source里面的内容到目标目录destination,则需要在源目录后面加上斜杠。

    
    $ rsync -a source/ destination
    

    上面命令执行后,source目录里面的内容,就都被复制到了destination目录里面,并不会在destination下面创建一个source子目录。

    3.3 -n 参数

    如果不确定 rsync 执行后会产生什么结果,可以先用-n--dry-run参数模拟执行的结果。

    
    $ rsync -anv source/ destination
    

    上面命令中,-n参数模拟命令执行的结果,并不真的执行命令。-v参数则是将结果输出到终端,这样就可以看到哪些内容会被同步。

    3.4 --delete 参数

    默认情况下,rsync 只确保源目录的所有内容(明确排除的文件除外)都复制到目标目录。它不会使两个目录保持相同,并且不会删除文件。如果要使得目标目录成为源目录的镜像副本,则必须使用--delete参数,这将删除只存在于目标目录、不存在于源目录的文件。

    
    $ rsync -av --delete source/ destination
    

    上面命令中,--delete参数会使得destination成为source的一个镜像。

    四、排除文件

    4.1 --exclude 参数

    有时,我们希望同步时排除某些文件或目录,这时可以用--exclude参数指定排除模式。

    
    $ rsync -av --exclude='*.txt' source/ destination
    # 或者
    $ rsync -av --exclude '*.txt' source/ destination
    

    上面命令排除了所有 TXT 文件。

    注意,rsync 会同步以”点”开头的隐藏文件,如果要排除隐藏文件,可以这样写--exclude=".*"

    如果要排除某个目录里面的所有文件,但不希望排除目录本身,可以写成下面这样。

    
    $ rsync -av --exclude 'dir1/*' source/ destination
    

    多个排除模式,可以用多个--exclude参数。

    
    $ rsync -av --exclude 'file1.txt' --exclude 'dir1/*' source/ destination
    

    多个排除模式也可以利用 Bash 的大扩号的扩展功能,只用一个--exclude参数。

    
    $ rsync -av --exclude={'file1.txt','dir1/*'} source/ destination
    

    如果排除模式很多,可以将它们写入一个文件,每个模式一行,然后用--exclude-from参数指定这个文件。

    
    $ rsync -av --exclude-from='exclude-file.txt' source/ destination
    

    4.2 --include 参数

    --include参数用来指定必须同步的文件模式,往往与--exclude结合使用。

    
    $ rsync -av --include="*.txt" --exclude='*' source/ destination
    

    上面命令指定同步时,排除所有文件,但是会包括 TXT 文件。

    五、远程同步

    5.1 SSH 协议

    rsync 除了支持本地两个目录之间的同步,也支持远程同步。它可以将本地内容,同步到远程服务器。

    
    $ rsync -av source/ username@remote_host:destination
    

    也可以将远程内容同步到本地。

    
    $ rsync -av username@remote_host:source/ destination
    

    rsync 默认使用 SSH 进行远程登录和数据传输。

    由于早期 rsync 不使用 SSH 协议,需要用-e参数指定协议,后来才改的。所以,下面-e ssh可以省略。

    
    $ rsync -av -e ssh source/ user@remote_host:/destination
    

    但是,如果 ssh 命令有附加的参数,则必须使用-e参数指定所要执行的 SSH 命令。

    
    $ rsync -av -e 'ssh -p 2234' source/ user@remote_host:/destination
    

    上面命令中,-e参数指定 SSH 使用2234端口。

    5.2 rsync 协议

    除了使用 SSH,如果另一台服务器安装并运行了 rsync 守护程序,则也可以用rsync://协议(默认端口873)进行传输。具体写法是服务器与目标目录之间使用双冒号分隔::

    
    $ rsync -av source/ 192.168.122.32::module/destination
    

    注意,上面地址中的module并不是实际路径名,而是 rsync 守护程序指定的一个资源名,由管理员分配。

    如果想知道 rsync 守护程序分配的所有 module 列表,可以执行下面命令。

    
    $ rsync rsync://192.168.122.32
    

    rsync 协议除了使用双冒号,也可以直接用rsync://协议指定地址。

    
    $ rsync -av source/ rsync://192.168.122.32/module/destination
    

    六、增量备份

    rsync 的最大特点就是它可以完成增量备份,也就是默认只复制有变动的文件。

    除了源目录与目标目录直接比较,rsync 还支持使用基准目录,即将源目录与基准目录之间变动的部分,同步到目标目录。

    具体做法是,第一次同步是全量备份,所有文件在基准目录里面同步一份。以后每一次同步都是增量备份,只同步源目录与基准目录之间有变动的部分,将这部分保存在一个新的目标目录。这个新的目标目录之中,也是包含所有文件,但实际上,只有那些变动过的文件是存在于该目录,其他没有变动的文件都是指向基准目录文件的硬链接。

    --link-dest参数用来指定同步时的基准目录。

    
    $ rsync -a --delete --link-dest /compare/path /source/path /target/path
    

    上面命令中,--link-dest参数指定基准目录/compare/path,然后源目录/source/path跟基准目录进行比较,找出变动的文件,将它们拷贝到目标目录/target/path。那些没变动的文件则会生成硬链接。这个命令的第一次备份时是全量备份,后面就都是增量备份了。

    下面是一个脚本示例,备份用户的主目录。

    
    #!/bin/bash
    
    # A script to perform incremental backups using rsync
    
    set -o errexit
    set -o nounset
    set -o pipefail
    
    readonly SOURCE_DIR="${HOME}"
    readonly BACKUP_DIR="/mnt/data/backups"
    readonly DATETIME="$(date '+%Y-%m-%d_%H:%M:%S')"
    readonly BACKUP_PATH="${BACKUP_DIR}/${DATETIME}"
    readonly LATEST_LINK="${BACKUP_DIR}/latest"
    
    mkdir -p "${BACKUP_DIR}"
    
    rsync -av --delete \
      "${SOURCE_DIR}/" \
      --link-dest "${LATEST_LINK}" \
      --exclude=".cache" \
      "${BACKUP_PATH}"
    
    rm -rf "${LATEST_LINK}"
    ln -s "${BACKUP_PATH}" "${LATEST_LINK}"
    

    上面脚本中,每一次同步都会生成一个新目录${BACKUP_DIR}/${DATETIME},并将软链接${BACKUP_DIR}/latest指向这个目录。下一次备份时,就将${BACKUP_DIR}/latest作为基准目录,生成新的备份目录。最后,再将软链接${BACKUP_DIR}/latest指向新的备份目录。

    七、配置项

    -a--archive参数表示存档模式,保存所有的元数据,比如修改时间(modification time)、权限、所有者等,并且软链接也会同步过去。

    --append参数指定文件接着上次中断的地方,继续传输。

    --append-verify参数跟--append参数类似,但会对传输完成后的文件进行一次校验。如果校验失败,将重新发送整个文件。

    -b--backup参数指定在删除或更新目标目录已经存在的文件时,将该文件更名后进行备份,默认行为是删除。更名规则是添加由--suffix参数指定的文件后缀名,默认是~

    --backup-dir参数指定文件备份时存放的目录,比如--backup-dir=/path/to/backups

    --bwlimit参数指定带宽限制,默认单位是 KB/s,比如--bwlimit=100

    -c--checksum参数改变rsync的校验方式。默认情况下,rsync 只检查文件的大小和最后修改日期是否发生变化,如果发生变化,就重新传输;使用这个参数以后,则通过判断文件内容的校验和,决定是否重新传输。

    --delete参数删除只存在于目标目录、不存在于源目标的文件,即保证目标目录是源目标的镜像。

    -e参数指定使用 SSH 协议传输数据。

    --exclude参数指定排除不进行同步的文件,比如--exclude="*.iso"

    --exclude-from参数指定一个本地文件,里面是需要排除的文件模式,每个模式一行。

    --existing--ignore-non-existing参数表示不同步目标目录中不存在的文件和目录。

    -h参数表示以人类可读的格式输出。

    -h--help参数返回帮助信息。

    -i参数表示输出源目录与目标目录之间文件差异的详细情况。

    --ignore-existing参数表示只要该文件在目标目录中已经存在,就跳过去,不再同步这些文件。

    --include参数指定同步时要包括的文件,一般与--exclude结合使用。

    --link-dest参数指定增量备份的基准目录。

    -m参数指定不同步空目录。

    --max-size参数设置传输的最大文件的大小限制,比如不超过200KB(--max-size='200k')。

    --min-size参数设置传输的最小文件的大小限制,比如不小于10KB(--min-size=10k)。

    -n参数或--dry-run参数模拟将要执行的操作,而并不真的执行。配合-v参数使用,可以看到哪些内容会被同步过去。

    -P参数是--progress--partial这两个参数的结合。

    --partial参数允许恢复中断的传输。不使用该参数时,rsync会删除传输到一半被打断的文件;使用该参数后,传输到一半的文件也会同步到目标目录,下次同步时再恢复中断的传输。一般需要与--append--append-verify配合使用。

    --partial-dir参数指定将传输到一半的文件保存到一个临时目录,比如--partial-dir=.rsync-partial。一般需要与--append--append-verify配合使用。

    --progress参数表示显示进展。

    -r参数表示递归,即包含子目录。

    --remove-source-files参数表示传输成功后,删除发送方的文件。

    --size-only参数表示只同步大小有变化的文件,不考虑文件修改时间的差异。

    --suffix参数指定文件名备份时,对文件名添加的后缀,默认是~

    -u--update参数表示同步时跳过目标目录中修改时间更新的文件,即不同步这些有更新的时间戳的文件。

    -v参数表示输出细节。-vv表示输出更详细的信息,-vvv表示输出最详细的信息。

    --version参数返回 rsync 的版本。

    -z参数指定同步时压缩数据。

  • PhpStorm折叠展开所有函数或者方法以及函数跳转

    windows下按下快捷`Ctrl`+`Shift`+`-`,这样就能折叠所有代码了。

    windows下按下快捷`Ctrl`+`Shift`+`+`,这样就能恢复打开所有代码了。

    在点击跳转函数后返回原位置

    Ctrl  Alt   ⬅左箭头

  • Composer 的安装

    Wondows 平台

    Wondows 平台上,我们只需要下载 Composer-Setup.exe 后,一步步安装即可。

    需要注意的是你需要开启 openssl 配置,我们打开 php 目录下的 php.ini,将 extension=php_openssl.dll 前面的分号去掉就可以了。

    安装成功后,我们可以通过命令窗口(cmd) 输入 composer –version 命令来查看是否安装成功:

    接下来我们可以更改阿里云 Composer 全量镜像:

    composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/

    取消配置:

    composer config -g --unset repos.packagist

    项目配置

    仅修改当前工程配置,仅当前工程可使用该镜像地址:

    composer config repo.packagist composer https://mirrors.aliyun.com/composer/

    取消配置:

    composer config --unset repos.packagist

    调试

    composer 命令增加 -vvv 可输出详细的信息,命令如下:

    composer -vvv require alibabacloud/sdk

    遇到问题?

    1. 建议先将Composer版本升级到最新:

    composer self-update

    2. 执行诊断命令:

    composer diagnose

    3. 清除缓存:

    composer clear

    4. 若项目之前已通过其他源安装,则需要更新 composer.lock 文件,执行命令:

    composer update --lock

    5. 重试一次

    Linux 平台

    Linux 平台可以使用以下命令来安装:

    # php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');"
    # php composer-setup.php
    
    All settings correct for using Composer
    Downloading...
    
    Composer (version 1.6.5) successfully installed to: /root/composer.phar
    Use it: php composer.phar

    移动 composer.phar,这样 composer 就可以进行全局调用:

    # mv composer.phar /usr/local/bin/composer

    切换为国内镜像:

    # composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/

    更新 composer:

    # composer selfupdate

    Mac OS 系统

    Mac OS 系统可以使用以下命令来安装:

    $ curl -sS https://getcomposer.org/installer | php
    $ sudo mv composer.phar /usr/local/bin/composer
    $ composer --version
    Composer version 1.7.2 2018-08-16 16:57:12

    切换为国内镜像:

    $ composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/

    更新 composer:

    $ composer selfupdate

    Composer 的使用

    要使用 Composer,我们需要先在项目的目录下创建一个 composer.json 文件,文件描述了项目的依赖关系。

    文件格式如下:

    {
        "require": {
            "monolog/monolog": "1.2.*"
        }
    }

    以上文件说明我们需要下载从 1.2 开始的任何版本的 monolog。

    接下来只要运行以下命令即可安装依赖包:

    composer install

    require 命令

    除了使用 install 命令外,我们也可以使用 require 命令快速的安装一个依赖而不需要手动在 composer.json 里添加依赖信息:

    $ composer require monolog/monolog

    Composer 会先找到合适的版本,然后更新composer.json文件,在 require 那添加 monolog/monolog 包的相关信息,再把相关的依赖下载下来进行安装,最后更新 composer.lock 文件并生成 php 的自动加载文件。

    update 命令

    update 命令用于更新项目里所有的包,或者指定的某些包:

    # 更新所有依赖
    $ composer update
    
    # 更新指定的包
    $ composer update monolog/monolog
    
    # 更新指定的多个包
    $ composer update monolog/monolog symfony/dependency-injection
    
    # 还可以通过通配符匹配包
    $ composer update monolog/monolog symfony/*

    需要注意的时,包能升级的版本会受到版本约束的约束,包不会升级到超出约束的版本的范围。例如如果 composer.json 里包的版本约束为 ^1.10,而最新版本为 2.0。那么 update 命令是不能把包升级到 2.0 版本的,只能最高升级到 1.x 版本。关于版本约束请看后面的介绍。

    remove 命令

    remove 命令用于移除一个包及其依赖(在依赖没有被其他包使用的情况下),如果依赖被其他包使用,则无法移除:

    $ composer remove monolog/monolog
    Loading composer repositories with package information
    Updating dependencies (including require-dev)
    Package operations: 0 installs, 0 updates, 2 removals
      - Removing psr/log (1.0.2)
      - Removing monolog/monolog (1.23.0)
    Generating autoload files

    search 命令

    search 命令可以搜索包:

    $ composer search monolog

    该命令会输出包及其描述信息,如果只想输出包名可以使用 –only-name 参数:

    $ composer search --only-name monolog

    show 命令

    show 命令可以列出当前项目使用到包的信息:

    # 列出所有已经安装的包
    $ composer show
    
    # 可以通过通配符进行筛选
    $ composer show monolog/*
    
    # 显示具体某个包的信息
    $ composer show monolog/monolog

    基本约束

    精确版本

    我们可以告诉 Composer 安装的具体版本,例如:1.0.2,指定 1.0.2 版本。

    范围

    通过使用比较操作符来指定包的范围。这些操作符包括:>,>=,<,<=,!=

    你可以定义多个范围,使用空格或者逗号 , 表示逻辑上的与,使用双竖线 || 表示逻辑上的或。其中与的优先级会大于或。 实例:

    • >=1.0
    • >=1.0 <2.0
    • >=1.0 <1.1 || >=1.2

    我们也可以通过使用连字符  来指定版本范围。

    连字符的左边表明了 >= 的版本,如果右边的版本不是完整的版本号,则会被使用通配符进行补全。例如1.0 - 2.0等同于>=1.0.0 <2.12.0相当于2.0.*),而1.0.0 - 2.1.0则等同于>=1.0.0 <=2.1.0

    通配符

    可以使用通配符来设置版本。1.0.*相当于>=1.0 <1.1
    例子:1.0.*

    波浪号 ~

    我们先通过后面这个例子去解释~操作符的用法:~1.2相当于>=1.2 <2.0.0,而~1.2.3相当于>=1.2.3 <1.3.0。对于使用Semantic Versioning作为版本号标准的项目来说,这种版本约束方式很实用。例如~1.2定义了最小的小版本号,然后你可以升级2.0以下的任何版本而不会出问题,因为按照Semantic Versioning的版本定义,小版本的升级不应该有兼容性的问题。简单来说,~定义了最小的版本,并且允许版本的最后一位版本号进行升级(没懂得话,请再看一边前面的例子)。
    例子:~1.2

    需要注意的是,如果~作用在主版本号上,例如~1,按照上面的说法,Composer可以安装版本1以后的主版本,但是事实上是~1会被当作~1.0对待,只能增加小版本,不能增加主版本。

    折音号 ^

    ^操作符的行为跟Semantic Versioning有比较大的关联,它允许升级版本到安全的版本。例如,^1.2.3相当于>=1.2.3 <2.0.0,因为在2.0版本前的版本应该都没有兼容性的问题。而对于1.0之前的版本,这种约束方式也考虑到了安全问题,例如^0.3会被当作>=0.3.0 <0.4.0对待。
    例子:^1.2.3


    版本稳定性

    如果你没有显式的指定版本的稳定性,Composer会根据使用的操作符,默认在内部指定为-dev或者-stable。例如:

    约束 内部约束
    1.2.3 =1.2.3.0-stable
    >1.2 >1.2.0.0-stable
    >=1.2 >=1.2.0.0-dev
    >=1.2-stable >=1.2.0.0-stable
    <1.3 <1.3.0.0-dev
    <=1.3 <=1.3.0.0-stable
    1 - 2 >=1.0.0.0-dev <3.0.0.0-dev
    ~1.3 >=1.3.0.0-dev <2.0.0.0-dev
    1.4.* >=1.4.0.0-dev <1.5.0.0-dev

    例子:1.0 - 2.0如果你想指定版本只要稳定版本,你可以在版本后面添加后缀-stable

    minimum-stability 配置项定义了包在选择版本时对稳定性的选择的默认行为。默认是stable。它的值如下(按照稳定性排序):devalphabetaRCstable。除了修改这个配置去修改这个默认行为,我们还可以通过稳定性标识(例如@stable@dev)来安装一个相比于默认配置不同稳定性的版本。例如:

    {
        "require": {
            "monolog/monolog": "1.0.*@beta",
            "acme/foo": "@dev"
        }
    }
  • windows 查看端口占用

    netstat -aon|findstr "8081"
    
    taskkill /f /t /im TIM.exe
    结束进程:
    
    taskkill /T /F /PID 9088 

    1、开始—->运行—->cmd,或者是window+R组合键,调出命令窗口:

    2、输入命令:netstat -ano,列出所有端口的情况。在列表中我们观察被占用的端口,比如是8080,首先找到它:

    3、查看被占用端口对应的PID,输入命令:netstat -aon|findstr “8080”,回车,记下最后一位数字,即PID,这里是2668。

    4、继续输入tasklist|findstr “2668”,回车,查看是哪个进程或者程序占用了2668端口,结果是:TIM.exe

    5、或者是我们打开任务管理器,点击查看—>选择列,将PID(进程标示符)前面的勾打上,点击确定。

    切换到进程选项卡,在PID一列查看2668对应的进程,如下图:

    6、结束该进程:在任务管理器中选中该进程点击”结束进程“按钮,或者是在cmd的命令窗口中输入:taskkill /f /t /im TIM.exe

    注:后两步可以使用任务管理器,因为看的比较直观而且方便。

  • docker 开启远程访问

    netsh interface portproxy add v4tov4 listenport=2375 connectaddress=127.0.0.1 connectport=2375 listenaddress=【your-public-ip】 protocol=tcp

  • “git pull” 如何强制覆盖本地文件

    git checkout master
    git branch new-branch-to-save-current-commits
    git fetch --all
    git reset --hard origin/master

    重要提示:如果您有任何本地更改,将会丢失。无论是否有–hard选项,任何未被推送的本地提交都将丢失。
    如果您有任何未被Git跟踪的文件(例如上传的用户内容),这些文件将不会受到影响。
    下面是正确的方法

    git fetch --all
    

    然后,你有两个选择:

    git reset --hard origin/master
    

    或者如果你在其他分支上:

    git reset --hard origin/<branch_name>