作者: houlijiang

  • MySQL中EXISTS的用法

    比如在Northwind数据库中有一个查询为

    SELECT c.CustomerId,CompanyName FROM Customers c
    WHERE EXISTS(
    SELECT OrderID FROM Orders o WHERE o.CustomerID=c.CustomerID) 

    这里面的EXISTS是如何运作呢?子查询返回的是OrderId字段,可是外面的查询要找的是CustomerID和CompanyName字段,这两个字段肯定不在OrderID里面啊,这是如何匹配的呢? 

    EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False
    EXISTS 指定一个子查询,检测 行 的存在。

    语法: EXISTS subquery
    参数: subquery 是一个受限的 SELECT 语句 (不允许有 COMPUTE 子句和 INTO 关键字)。
    结果类型: Boolean 如果子查询包含行,则返回 TRUE ,否则返回 FLASE 。

    例表A:TableIn 例表B:TableEx
    tableA tableB


    (一). 在子查询中使用 NULL 仍然返回结果集
    select * from TableIn where exists(select null)
    等同于: select * from TableIn
    tableA 
    (二). 比较使用 EXISTS 和 IN 的查询。注意两个查询返回相同的结果。
    select * from TableIn where exists(select BID from TableEx where BNAME=TableIn.ANAME)
    select * from TableIn where ANAME in(select BNAME from TableEx)
    008
    (三). 比较使用 EXISTS 和 = ANY 的查询。注意两个查询返回相同的结果。
    select * from TableIn where exists(select BID from TableEx where BNAME=TableIn.ANAME)
    select * from TableIn where ANAME=ANY(select BNAME from TableEx)
    008
    NOT EXISTS 的作用与 EXISTS 正好相反。如果子查询没有返回行,则满足了 NOT EXISTS 中的 WHERE 子句。

    结论:
      EXISTS(包括 NOT EXISTS )子句的返回值是一个BOOL值。 EXISTS内部有一个子查询语句(SELECT … FROM…), 我将其称为EXIST的内查询语句。其内查询语句返回一个结果集。 EXISTS子句根据其内查询语句的结果集空或者非空,返回一个布尔值。

    一种通俗的可以理解为:将外查询表的每一行,代入内查询作为检验,如果内查询返回的结果取非空值,则EXISTS子句返回TRUE,这一行行可作为外查询的结果行,否则不能作为结果。

    例如:

    1.  查询id为5的数据:  (数据存在)

    copycode
        SELECT *
        FROM class AS c1
        WHERE EXISTS(SELECT
                   class_id
                 FROM class AS c2
                 WHERE c1.class_id = 
    5);
    copycode

      如果exists里面返回的结果行数大于1,则返回true,则外面的查询数据可以返回。

    1196212-20180318224033032-740838109

     2.  查询id为10的数据:  (数据不存在)

    copycode
        SELECT *
        FROM class AS c1
        WHERE EXISTS(SELECT
                   class_id
                 FROM class AS c2
                 WHERE c1.class_id = 
    10);
    copycode

       因为exsits始终返回的是false,所以外层查询始终无效,也就不会产生数据。

     

      

      分析器会先看语句的第一个词,当它发现第一个词是SELECT关键字的时候,它会跳到FROM关键字,然后通过FROM关键字找到表名并把表装入内存。接着是找WHERE关键字,如果找不到则返回到SELECT找字段解析,如果找到WHERE,则分析其中的条件,完成后再回到SELECT分析字段。最后形成一张我们要的虚表。
      WHERE关键字后面的是条件表达式。条件表达式计算完成后,会有一个返回值,即非0或0,非0即为真(true),0即为假(false)。同理WHERE后面的条件也有一个返回值,真或假,来确定接下来执不执行SELECT。
      分析器先找到关键字SELECT,然后跳到FROM关键字将STUDENT表导入内存,并通过指针找到第一条记录,接着找到WHERE关键字计算它的条件表达式,如果为真那么把这条记录装到一个虚表当中,指针再指向下一条记录。如果为假那么指针直接指向下一条记录,而不进行其它操作。一直检索完整个表,并把检索出来的虚拟表返回给用户。EXISTS是条件表达式的一部分,它也有一个返回值(true或false)。

    在插入记录前,需要检查这条记录是否已经存在,只有当记录不存在时才执行插入操作,可以通过使用 EXISTS 条件句防止插入重复记录。
    INSERT INTO TableIn (ANAME,ASEX) 
    SELECT top 1 ‘张三’, ‘男’ FROM TableIn
    WHERE not exists (select * from TableIn where TableIn.AID = 7)

    EXISTS与IN的使用效率的问题,通常情况下采用exists要比in效率高,但要看实际情况具体使用:
    IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况。

    in、not in、exists和not exists的区别:

    先谈谈in和exists的区别:
    exists:存在,后面一般都是子查询,当子查询返回行数时,exists返回true。

    select * from class where exists (select'x"form stu where stu.cid=class.cid)


    当in和exists在查询效率上比较时,in查询的效率快于exists的查询效率
    exists(xxxxx)后面的子查询被称做相关子查询, 他是不返回列表的值的.
    只是返回一个ture或false的结果(这也是为什么子查询里是select ‘x’的原因 当然也可以
    select任何东西) 也就是它只在乎括号里的数据能不能查找出来,是否存在这样的记录。

    其运行方式是先运行主查询一次 再去子查询里查询与其对应的结果 如果存在,返回ture则输 出,反之返回false则不输出,再根据主查询中的每一行去子查询里去查询.

    执行顺序如下:
    1.首先执行一次外部查询
    2.对于外部查询中的每一行分别执行一次子查询,而且每次执行子查询时都会引用外部查询中当
    前行的值。

    3.使用子查询的结果来确定外部查询的结果集。
    如果外部查询返回100行,SQL   就将执行101次查询,一次执行外部查询,然后为外部查询返回
    的每一行执行一次子查询。

    in:包含

    查询和所有女生年龄相同的男生

    select * from stu where sex=’男’ and age in(select age from stu where sex=’女’)


    in()后面的子查询 是返回结果集的,换句话说执行次序和exists()不一样.子查询先产生结果集,然后主查询再去结果集里去找符合要求的字段列表去.符合要求的输出,反之则不输出.


    not in和not exists的区别:
    not in 只有当子查询中,select 关键字后的字段有not null约束或者有这种暗示时用not in,另外如果主查询中表大,子查询中的表小但是记录多,则应当使用not in,
    例如:查询那些班级中没有学生的,
    select * from class where cid not in(select distinct cid from stu)
    当表中cid存在null值,not in 不对空值进行处理
    解决:select * from class

    where cid not in

    (select distinct cid from stu where cid is not null)


    not in的执行顺序是:是在表中一条记录一条记录的查询(查询每条记录)符合要求的就返回结果集,不符合的就继续查询下一条记录,直到把表中的记录查询完。也就是说为了证明找不到,所以只能查询全部记录才能证明。并没有用到索引。
    not exists:如果主查询表中记录少,子查询表中记录多,并有索引。
    例如:查询那些班级中没有学生的,
    select * from class2

    where not exists

    (select * from stu1 where stu1.cid =class2.cid)


    not exists的执行顺序是:在表中查询,是根据索引查询的,如果存在就返回true,如果不存在就返回false,不会每条记录都去查询。
    之所以要多用not exists,而不用not in,也就是not exists查询的效率远远高与not in查询的效率。

     实例:

    exists,not exists的使用方法示例,需要的朋友可以参考下。

    学生表:create table student
    (
     id number(8) primary key,
     name varchar2(10),deptment number(8)
    )
    选课表:create table select_course
    (
      ID         NUMBER(8) primary key,
      STUDENT_ID NUMBER(8) foreign key (COURSE_ID) references course(ID),
      COURSE_ID  NUMBER(8) foreign key (STUDENT_ID) references student(ID)
    )
    课程表:create table COURSE
    (
      ID     NUMBER(8) not null,
      C_NAME VARCHAR2(20),
      C_NO   VARCHAR2(10)
    )
    student表的数据:
            ID NAME            DEPTMENT_ID
    ---------- --------------- -----------
             1 echo                   1000
             2 spring                 2000
             3 smith                  1000
             4 liter                  2000
    course表的数据:
            ID C_NAME               C_NO
    ---------- -------------------- --------
             1 数据库               data1
             2 数学                 month1
             3 英语                 english1
    select_course表的数据:
            ID STUDENT_ID  COURSE_ID
    ---------- ---------- ----------
             1    1         1
             2    1         2
             3    1         3
             4    2         1
             5    2         2
             6    3         2
    1.查询选修了所有课程的学生id、name:(即这一个学生没有一门课程他没有选的。)
    分析:如果有一门课没有选,则此时(1)select * from select_course sc where sc.student_id=ts.id 
    and sc.course_id=c.id存在null,
    这说明(2)select * from course c 的查询结果中确实有记录不存在(1查询中),查询结果返回没有选的课程,
    此时select * from t_student ts 后的not exists 判断结果为false,不执行查询。
    SQL> select * from t_student ts where not exists
     (select * from course c where not exists
       (select * from select_course sc where sc.student_id=ts.id and sc.course_id=c.id));       
            ID NAME            DEPTMENT_ID
    ---------- --------------- -----------
             1 echo                   1000
    2.查询没有选择所有课程的学生,即没有全选的学生。(存在这样的一个学生,他至少有一门课没有选),
    分析:只要有一个门没有选,即select * from select_course sc where student_id=t_student.id and course_id
    =course.id 有一条为空,即not exists null 为true,此时select * from course有查询结果(id为子查询中的course.id ),
    因此select id,name from t_student 将执行查询(id为子查询中t_student.id )。
    SQL> select id,name from t_student where exists
     (select * from course where not exists
         (select * from select_course sc where student_id=t_student.id and course_id=course.id));
            ID NAME
    ---------- ---------------
             2 spring
             3 smith
             4 liter
    3.查询一门课也没有选的学生。(不存这样的一个学生,他至少选修一门课程),
    分析:如果他选修了一门select * from course结果集不为空,not exists 判断结果为false;
    select id,name from t_student 不执行查询。
    SQL> select id,name from t_student where not exists
     (select * from course where exists
         (select * from select_course sc where student_id=t_student.id and course_id=course.id));
            ID NAME
    ---------- ---------------
             4 liter
    4.查询至少选修了一门课程的学生。
    SQL> select id,name from t_student where exists
     (select * from course where  exists
         (select * from select_course sc where student_id=t_student.id and course_id=course.id));
            ID NAME
    ---------- ---------------
             1 echo
             2 spring
             3 smith


    补充:in 走不走索引还是要视情况而定

    in在某些情况下会走、某些情况下不会走索引。  有些情况下Mysql会判断不走索引更快,会进行全表扫描,比如数据量只有几条的时候;在数据量大的时候in会走索引
    测试如下:
    (1) 查看索引
    show index from user;
    1196212-20210226102338424-173474452

     (2)   数据量只有两条的时候测试: 这时候没有走索引,走的全表扫描

    1196212-20210226102355054-669707660

     (3) 数据量大的时候进行的测试(数据量到达千条以上)

    1196212-20210226102420204-1575624160

      测试二: 子查询测试

    1196212-20210226102435261-1596447844
  • mysql查询按照指定字段的指定顺序进行排序

    之前我们已经了解的mysql按照中文进行排序的实现方法了:https://www.wj0511.com/site/detail.html?id=420

    那么如何按照指定字段的指定顺序进行排序呢?

    例如有一个用户表user,有id,username,status字段,status的字段值有1,2,3,4四种情况,如何将用户表中的数据按照status字段的2,4,1,3顺序进行排序呢?

    这时候需要使用到FIELD或者FIND_IN_SET方法,如:

    SELECT * FROM user ORDER BY FIELD(status,2,4,1,3)

    SELECT * FROM user ORDER BY FIND_IN_SET(status,'2,4,1,3') 

    如上两种方法就可以实现按照指定字段的指定顺序进行排序了

    在Yii框架中实现如下

    User::find()  
        ->orderBy([  
            new \yii\db\Expression('FIELD (status,2,4,1,3'),  
        ])  
        ->all()
  • aliyundrive-webdav

    aliyundrive-webdav

     

    GitHub Actions
    PyPI
    Docker Image
    aliyundrive-webdav
    Crates.io

    1f680.svg_ Help me to become a full-time open-source developer by sponsoring me on GitHub

    阿里云盘 WebDAV 服务,主要使用场景为配合支持 WebDAV 协议的客户端 App 如 InfusenPlayer 等实现在电视上直接观看云盘视频内容, 支持客户端 App 直接从阿里云盘获取文件播放而不经过运行本应用的服务器中转, 支持上传文件,但受限于 WebDAV 协议不支持文件秒传。

    请注意:V2 版本基于阿里云盘开放平台接口实现,不再支持阿里云盘 Web 和 App 版本获取的 refresh token。 由于本项目作者不再使用梅林固件,V2 版本不再免费支持 Koolshare 梅林固件系统,如有需要请考虑付费支持

    如果项目对你有帮助,请考虑捐赠支持项目持续维护。 也可以考虑加入aliyundrive-webdav 知识星球获取咨询和技术支持服务。

    Note

    本项目作者没有上传需求, 故上传文件功能测试不全面且没有持续迭代计划.

    安装

     

    可以从 GitHub Releases 页面下载预先构建的二进制包, 也可以使用 pip 从 PyPI 下载:

    pip install aliyundrive-webdav

    如果系统支持 Snapcraft 比如 Ubuntu、Debian 等,也可以使用 snap 安装:

    sudo snap install aliyundrive-webdav

    OpenWrt 路由器

     

    GitHub Releases 中有预编译的 ipk 文件, 目前提供了 aarch64/arm/mipsel/x86_64/i686 等架构的版本,可以下载后使用 opkg 安装,以 nanopi r4s 为例:

    wget https://github.com/messense/aliyundrive-webdav/releases/download/v2.3.3/aliyundrive-webdav_2.3.3-1_aarch64_generic.ipk
    wget https://github.com/messense/aliyundrive-webdav/releases/download/v2.3.3/luci-app-aliyundrive-webdav_2.3.3_all.ipk
    wget https://github.com/messense/aliyundrive-webdav/releases/download/v2.3.3/luci-i18n-aliyundrive-webdav-zh-cn_2.3.3-1_all.ipk
    opkg install aliyundrive-webdav_2.3.3-1_aarch64_generic.ipk
    opkg install luci-app-aliyundrive-webdav_2.3.3_all.ipk
    opkg install luci-i18n-aliyundrive-webdav-zh-cn_2.3.3-1_all.ipk

    其它 CPU 架构的路由器可在 GitHub Releases 页面中查找对应的架构的主程序 ipk 文件下载安装, 常见 OpenWrt 路由器 CPU 架构如下表(欢迎补充):

    路由器 CPU 架构
    nanopi r4s aarch64_generic
    小米 AX3600 aarch64_cortex-a53
    斐讯 N1 盒子 aarch64_cortex-a53
    Newifi D2 mipsel_24kc
    Pogoplug arm_mpcore

    Tips: 不清楚 CPU 架构类型可通过运行 opkg print-architecture 命令查询。

    OpenWrt 配置界面

    Docker 运行

     

    docker run -d --name=aliyundrive-webdav --restart=unless-stopped -p 8080:8080 \
      -v /etc/aliyundrive-webdav/:/etc/aliyundrive-webdav/ \
      -e REFRESH_TOKEN='your refresh token' \
      -e WEBDAV_AUTH_USER=admin \
      -e WEBDAV_AUTH_PASSWORD=admin \
      messense/aliyundrive-webdav

    其中,REFRESH_TOKEN 环境变量为你的阿里云盘 refresh_tokenWEBDAV_AUTH_USER 和 WEBDAV_AUTH_PASSWORD 为连接 WebDAV 服务的用户名和密码。

    QNAP 威联通 NAS

     

    QNAP 插件

     

    qnap-aliyunpan-webdav by @iranee.

    ContainerStation (Docker)

     

    管理员登陆 NAS 后安装 ContainerStation 并启动服务,在 Management (管理) 标签中 Create Application (新建应用),配置如下

    version: '3.3'
    services:
      aliyundrive-webdav:
        container_name: aliyundrive-webdav
        restart: unless-stopped
        ports:
          - '8080:8080'
        environment:
          - 'REFRESH_TOKEN=mytoken...'
        image: messense/aliyundrive-webdav

    其中 REFRESH_TOKEN 文档最下面说明;:8080 网盘访问映射端口,可以按需改为其他的。

    点击 Create (创建)后启动,访问 http://nas地址:8080/ 即可看到你网盘的自动生成索引网页文件。

    参考文档

    rclone

     

    为了避免重复上传文件,使用 rclone 时推荐使用 Nextcloud WebDAV 模式,可以支持 sha1 checksums. 另外需要配合 --no-update-modtime 参数,否则 rclone 为了更新文件修改时间还是会强制重新上传。

    举个例子:

    rclone --no-update-modtime copy abc.pdf aliyundrive-nc://docs/

    获取 refresh token

     

    扫码获取 refresh token

    命令行用法

     

    $ aliyundrive-webdav --help
    WebDAV server for AliyunDrive
    
    Usage: aliyundrive-webdav [OPTIONS]
           aliyundrive-webdav <COMMAND>
    
    Commands:
      qr    Scan QRCode
      help  Print this message or the help of the given subcommand(s)
    
    Options:
          --host <HOST>
              Listen host
    
              

    [env: HOST=]

    [default: 0.0.0.0]

    -p, –port <PORT> Listen port

    [env: PORT=]

    [default: 8080]

    –client-id <CLIENT_ID> Aliyun drive client_id

    [env: CLIENT_ID=]

    –client-secret <CLIENT_SECRET> Aliyun drive client_secret

    [env: CLIENT_SECRET=]

    –drive-type <DRIVE_TYPE> Aliyun drive type

    [env: DRIVE_TYPE=]

    Possible values: – resource: Resource drive – backup: Backup drive – default: Default drive -r, –refresh-token <REFRESH_TOKEN> Aliyun drive refresh token

    [env: REFRESH_TOKEN=]

    -U, –auth-user <AUTH_USER> WebDAV authentication username

    [env: WEBDAV_AUTH_USER=]

    -W, –auth-password <AUTH_PASSWORD> WebDAV authentication password

    [env: WEBDAV_AUTH_PASSWORD=]

    -I, –auto-index Automatically generate index.html -S, –read-buffer-size <READ_BUFFER_SIZE> Read/download buffer size in bytes, defaults to 10MB

    [default: 10485760]

    –upload-buffer-size <UPLOAD_BUFFER_SIZE> Upload buffer size in bytes, defaults to 16MB

    [default: 16777216]

    –cache-size <CACHE_SIZE> Directory entries cache size

    [default: 1000]

    –cache-ttl <CACHE_TTL> Directory entries cache expiration time in seconds

    [default: 600]

    –root <ROOT> Root directory path

    [env: WEBDAV_ROOT=]

    [default: /]

    -w, –workdir <WORKDIR> Working directory, refresh_token will be stored in there if specified –no-trash Delete file permanently instead of trashing it –read-only Enable read only mode –tls-cert <TLS_CERT> TLS certificate file path

    [env: TLS_CERT=]

    –tls-key <TLS_KEY> TLS private key file path

    [env: TLS_KEY=]

    –strip-prefix <STRIP_PREFIX> Prefix to be stripped off when handling request

    [env: WEBDAV_STRIP_PREFIX=]

    –debug Enable debug log –no-self-upgrade Disable self auto upgrade –skip-upload-same-size Skip uploading same size file –prefer-http-download Prefer downloading using HTTP protocol –redirect Enable 302 redirect when possible -h, –help Print help (see a summary with ‘-h’) -V, –version Print version

    [env: HOST=]

    [default: 0.0.0.0]

    -p, –port Listen port

    [env: PORT=]

    [default: 8080]

    –client-id Aliyun drive client_id

    [env: CLIENT_ID=]

    –client-secret Aliyun drive client_secret

    [env: CLIENT_SECRET=]

    –drive-type Aliyun drive type

    [env: DRIVE_TYPE=]

    Possible values: – resource: Resource drive – backup: Backup drive – default: Default drive -r, –refresh-token Aliyun drive refresh token

    [env: REFRESH_TOKEN=]

    -U, –auth-user WebDAV authentication username

    [env: WEBDAV_AUTH_USER=]

    -W, –auth-password WebDAV authentication password

    [env: WEBDAV_AUTH_PASSWORD=]

    -I, –auto-index Automatically generate index.html -S, –read-buffer-size Read/download buffer size in bytes, defaults to 10MB

    [default: 10485760]

    –upload-buffer-size Upload buffer size in bytes, defaults to 16MB

    [default: 16777216]

    –cache-size Directory entries cache size

    [default: 1000]

    –cache-ttl Directory entries cache expiration time in seconds

    [default: 600]

    –root Root directory path

    [env: WEBDAV_ROOT=]

    [default: /]

    -w, –workdir Working directory, refresh_token will be stored in there if specified –no-trash Delete file permanently instead of trashing it –read-only Enable read only mode –tls-cert TLS certificate file path

    [env: TLS_CERT=]

    –tls-key TLS private key file path

    [env: TLS_KEY=]

    –strip-prefix Prefix to be stripped off when handling request

    [env: WEBDAV_STRIP_PREFIX=]

    –debug Enable debug log –no-self-upgrade Disable self auto upgrade –skip-upload-same-size Skip uploading same size file –prefer-http-download Prefer downloading using HTTP protocol –redirect Enable 302 redirect when possible -h, –help Print help (see a summary with ‘-h’) -V, –version Print version” tabindex=”0″ role=”button” style=”box-sizing: border-box; position: relative; display: flex !important; padding: 0px !important; font-size: 14px; font-weight: var(–base-text-weight-medium, 500); line-height: 20px; white-space: nowrap; vertical-align: middle; cursor: pointer; user-select: none; border: 0px; border-radius: 6px; appearance: none; color: var(–fgColor-accent, var(–color-accent-fg)); background-color: transparent; box-shadow: none; transition: color 80ms cubic-bezier(0.33, 1, 0.68, 1) 0s, background-color, box-shadow, border-color; justify-content: center !important; align-items: center !important; margin: var(–base-size-8, 8px) !important; width: var(–control-small-size, 28px); height: var(–control-small-size, 28px);”>

    Note

    注意:TLS/HTTPS 暂不支持 MIPS 架构。

    Note

    注意:启用 --skip-upload-same-size 选项虽然能加速上传但可能会导致修改过的同样大小的文件不会被上传

    License

     

    This work is released under the MIT license. A copy of the license is provided in the LICENSE file.

  • centos端口不通

    检测网络:iptables -S -t nat

     iptables -P  FORWARD  ACCEPT

    开机自启:

    vim   /etc/rc.local 
    iptables -P FORWARD   ACCEPT
  • tcpdump抓包工具命令–详解

    tcpdump是工作中必用的一道指令,如果熟悉掌握,将会很快的帮你解决问题!文章写的有点多,但是我认为都很有用!

     

    参数列表

      设置不解析域名提升速度  
    -n 不把ip转化成域名,直接显示 ip,避免执行 DNS lookups 的过程,速度会快很多  
    -nn 不把协议和端口号转化成名字,速度也会快很多。  
    -N 不打印出host 的域名部分.。比如,,如果设置了此选现,tcpdump 将会打印’nic’ 而不是 ‘nic.ddn.mil’.  
         
      过滤指定网卡的数据包  
    -i 指定要过滤的网卡接口,如果要查看所有网卡,可以 -i any  
         
      过滤特定流向的数据包  
    -Q 选择是入方向还是出方向的数据包,可选项有:in, out, inout,也可以使用 –direction=[direction] 这种写法  
         
      常用的一些参数  
    -A 以ASCII码方式显示每一个数据包(不显示链路层头部信息). 在抓取包含网页数据的数据包时, 可方便查看数据  
    -l 基于行的输出,便于你保存查看,或者交给其它工具分析
    tcpdump -nn -A -s1500 -l | egrep -i ‘User-Agent:|Host’
    通过 egrep 可以同时提取用户代理和主机名(或其他头文件):
     
    -q 简洁地打印输出。即打印很少的协议相关信息, 从而输出行都比较简短.  
    -c 捕获 count 个包 tcpdump 就退出  
    -s tcpdump 默认只会截取前 96 字节的内容,要想截取所有的报文内容,可以使用 -s number, number 就是你要截取的报文字节数,如果是 0 的话,表示截取报文全部内容。  
    -S 使用绝对序列号,而不是相对序列号  
    -C file-size,tcpdump 在把原始数据包直接保存到文件中之前, 检查此文件大小是否超过file-size. 如果超过了, 将关闭此文件,另创建一个文件继续用于原始数据包的记录. 新创建的文件名与-w 选项指定的文件名一致, 但文件名后多了一个数字.该数字会从1开始随着新创建文件的增多而增加. file-size的单位是百万字节(nt: 这里指1,000,000个字节,并非1,048,576个字节, 后者是以1024字节为1k, 1024k字节为1M计算所得, 即1M=1024 * 1024 = 1,048,576)  
    -F 使用file 文件作为过滤条件表达式的输入, 此时命令行上的输入将被忽略.  
         
      过滤结果输出到文件  
    -w 使用 -w 参数后接一个以 .pcap 后缀命令的文件名,就可以将 tcpdump 抓到的数据保存到文件中。使用 wireshark 打开此文件便可进行分析 tcpdump icmp -w icmp.pcap
    -r 从文件中读取数据,读取后,我们照样可以使用上述的过滤器语法进行过滤分析。 tcpdump icmp -r all.pcap
         
      对输出内容进行控制的参数  
    -D 显示所有可用网络接口的列表  
    -e 每行的打印输出中将包括数据包的数据链路层头部信息  
    -E 揭秘IPSEC数据  
    -L 列出指定网络接口所支持的数据链路层的类型后退出  
    -Z 后接用户名,在抓包时会受到权限的限制。如果以root用户启动tcpdump,tcpdump将会有超级用户权限。  
    -d 打印出易读的包匹配码  
    -dd 以C语言的形式打印出包匹配码.  
    -ddd 以十进制数的形式打印出包匹配码  
         
      控制详细内容的输出  
    -v 产生详细的输出. 比如包的TTL,id标识,数据包长度,以及IP包的一些选项。同时它还会打开一些附加的包完整性检测,比如对IP或ICMP包头部的校验和。  
    -vv 产生比-v更详细的输出. 比如NFS回应包中的附加域将会被打印, SMB数据包也会被完全解码。(摘自网络,目前我还未使用过)  
    -vvv 产生比-vv更详细的输出。比如 telent 时所使用的SB, SE 选项将会被打印, 如果telnet同时使用的是图形界面,其相应的图形选项将会以16进制的方式打印出来(摘自网络,目前我还未使用过)  
         
      控制时间的显示  
    -t 在每行的输出中不输出时间  
    -tt 在每行的输出中会输出时间戳  
    -ttt 输出每两行打印的时间间隔(以毫秒为单位)  
    -tttt 在每行打印的时间戳之前添加日期的打印(此种选项,输出的时间最直观)  
         
      显示数据包的头部  
    -x 以16进制的形式打印每个包的头部数据(但不包括数据链路层的头部)  
    -xx 以16进制的形式打印每个包的头部数据(包括数据链路层的头部)  
    -X 以16进制和 ASCII码形式打印出每个包的数据(但不包括连接层的头部),这在分析一些新协议的数据包很方便。  
    -XX 以16进制和 ASCII码形式打印出每个包的数据(包括连接层的头部),这在分析一些新协议的数据包很方便。  

    过滤规则组合

    有编程基础的同学,对于下面三个逻辑运算符应该不陌生了吧

    • and:所有的条件都需要满足,也可以表示为 &&
    • or:只要有一个条件满足就可以,也可以表示为 ||
    • not:取反,也可以使用 !

    举个例子,我想需要抓一个来自10.5.2.3,发往任意主机的3389端口的包

    $ tcpdump src 10.5.2.3 and dst port 3389
    

    当你在使用多个过滤器进行组合时,有可能需要用到括号,而括号在 shell 中是特殊符号,因为你需要使用引号将其包含。例子如下:

    $ tcpdump 'src 10.0.2.4 and (dst port 3389 or 22)'

    而在单个过滤器里,常常会判断一条件是否成立,这时候,就要使用下面两个符号

    • =:判断二者相等
    • ==:判断二者相等
    • !=:判断二者不相等

    当你使用这两个符号时,tcpdump 还提供了一些关键字的接口来方便我们进行判断,比如

    • if:表示网卡接口名、
    • proc:表示进程名
    • pid:表示进程 id
    • svc:表示 service class
    • dir:表示方向,in 和 out
    • eproc:表示 effective process name
    • epid:表示 effective process ID

    内容输出结构

    21
    :
    26
    :
    49.013621 IP 172.20
    .20
    .1
    .15605 > 172.20
    .20
    .2
    .5920
    : Flags [
    P
    .
    ]
    , seq 49
    :
    97
    , ack 106048
    , win 4723
    , length 48

    从上面的输出来看,可以总结出:

    1. 第一列:时分秒毫秒 21:26:49.013621
    2. 第二列:网络协议 IP
    3. 第三列:发送方的ip地址+端口号,其中172.20.20.1是 ip,而15605 是端口号
    4. 第四列:箭头 >, 表示数据流向
    5. 第五列:接收方的ip地址+端口号,其中 172.20.20.2 是 ip,而5920 是端口号
    6. 第六列:冒号
    7. 第七列:数据包内容,包括Flags 标识符,seq 号,ack 号,win 窗口,数据长度 length,其中 [P.] 表示 PUSH 标志位为 1,更多标识符见下面

    理解 Flag 标识符

    截取数据只是第一步,第二步就是理解这些数据,下面就解释一下 tcpdump 命令输出各部分的意义。

    21:27:06.995846 IP (tos 0x0, ttl 64, id 45646, offset 0, flags [DF], proto TCP (
    6
    ), length 64
    )
        192.168.1.106.56166 > 124.192.132.54.80: Flags [S], cksum 0xa730 (correct), seq 992042666, win 65535, options [mss 1460,nop,wscale 4,nop,nop,TS val 663433143 ecr 0,sackOK,eol], length 0
    
    21:27:07.030487 IP (tos 0x0, ttl 51, id 0, offset 0, flags [DF], proto TCP (
    6
    ), length 44
    )
        124.192.132.54.80 > 192.168.1.106.56166: Flags [S.], cksum 0xedc0 (correct), seq 2147006684, ack 992042667, win 14600, options [mss 1440
    ], length 0
    
    21:27:07.030527 IP (tos 0x0, ttl 64, id 59119, offset 0, flags [DF], proto TCP (
    6
    ), length 40
    )
        192.168.1.106.56166 > 124.192.132.54.80: Flags [.], cksum 0x3e72 (correct), ack 2147006685, win 65535, length 0
    

     

    最基本也是最重要的信息就是数据报的源地址/端口和目的地址/端口,上面的例子第一条数据报中,源地址 ip 是 192.168.1.106,源端口是 56166,目的地址是 124.192.132.54,目的端口是 80。 > 符号代表数据的方向。

    此外,上面的三条数据还是 tcp 协议的三次握手过程,第一条就是 SYN 报文,这个可以通过 Flags [S] 看出。下面是常见的 TCP 报文的 Flags:

    • [S] : SYN(开始连接)
    • [.] : 没有 Flag
    • [P] : PSH(推送数据)
    • [F] : FIN (结束连接)
    • [R] : RST(重置连接)

    而第二条数据的 [S.] 表示 SYN-ACK,就是 SYN 报文的应答报文。

     

    先看看 tcpdump 的具体参数及意义:

    -i :指定 tcpdump 监听的网络接口

    -s :指定要监听数据包的长度

    -c :指定要监听的数据包数量,达到指定数量后自动停止抓包

    -w :指定将监听到的数据包写入文件中保存

    -A :指定将每个监听到的数据包以 ACSII 可见字符打印

    -n :指定将每个监听到数据包中的域名转换成 IP 地址后显示

    -nn :指定将每个监听到的数据包中的域名转换成 IP 、端口从应用名称转换成端口号后显示

    -e :指定将监听到的数据包链路层的信息打印出来,包括源 mac 和目的 mac ,以及网络层的协议

    -p :将网卡设置为非混杂模式,不能与 host broadcast 一起使用

    -r :指定从某个文件中读取数据包

    -S :指定打印每个监听到的数据包的 TCP 绝对序列号而非相对序列号

    OK ,参数介绍先到这里,下面看几个具体例子

    先来看一个比较基本的用法:

    #tcpdump -i eth0
    @eth0为参数值,表示需要抓包的网口,这是个必需参数哦。

    tcpdump 支持很多的关键字,下面先看几个例子:

    #tcpdump -i eth0 host 192.168.0.250 
    @在网口eth0上抓取主机地址为192.168.0.250的所有数据包。
    #tcpdump -i eth0 net 192.168.0.0/24 
    @在网口eth0上抓取网络地址为192.168.0.0/24的所有数据包
    #tcpdump -i eth0 port 80 
    @在网口eth0上抓取端口为80的所有数据包(注意,这里不区分是源端口还是目的端口)
    当然,我们也可以指定源端口或目的端口
    #tcpdump -i eth0 src port 80 and dst port 6100
    @在网口eth0上抓取源端口为80且目的端口为6100的数据包,这里用到了and逻辑运算符,后面再介绍
    #tcpdump -i eth0 icmp 
    @在网口eth0上抓取所有icmp协议的数据包
    以上几个例子,可以大致体现出tcpdump的基本用法。

    实际上, tcpdump 主要包括三种类型的关键字,第一种是关于类型的关键字,主要包括 host net port ,如上面的例( 1 )( 2 )( 3 ),第二种 是确定传输方向的关键字,主要包括 src dst src or dst src and dst ,这些关键字指明了传输的方向,如上面的例( 4 )。第三种是协议关键字,包括 fddi ip arp rarp tcp udp imcp 等,如上面的例( 5 )。

    除了这三种类型的关键字外,还有其他重要的关键字,如: gateway broadcast less greater ,还有三种逻辑运算,取非运算是 ‘not’ ‘!’ ,与运算符是 ‘and’ ‘&&’

    或运算符是 ‘or’ ‘||’ ,这些关键字可以组合起来构成强大的组合条件来满足我们的需求。

    #tcpdump -i eth0 -s 1400 -nn host 192.168.0.250 and ! 192.168.0.74 and icmp -e
    @抓取网口eth0上192.168.0.250与除192.168.0.74外的其他主机之间的icmp报文
    #tcpdump -i eth0 -s 1400 -nn tcp and \(host 192.168.0.250 and ! 192.168.0.74\)
    @抓取网口eth0上192.168.0.250与除192.168.0.74外的所有tcp数据包,
    这里用到了括号,注意,在tcpdump中使用括号时必须用转义
    #tcpdump -i eth0 ether src or dst 00:21:85:6C:D9:A3
    @抓取网口eth0上源mac地址或目的mac地址为00:21:85:6C:D9:A3的所有数据包,
    注意,这里的mac地址格式必须以':'分隔。
  • Win11怎么安装安卓应用?Win11安装安卓应用教程

    Win11安装安卓应用教程

      1、首先,我们要确保自己的电脑支持虚拟化。

      2、如果没有开启的话,可以进入windows功能中开启它。

      1) 操作简单,大家先按下快捷键“win+r”输入control,然后进入控制面板。

      2) 然后点击“程序”。

      3) 在程序右侧点击“启用或关闭windows功能”。

      4) 最后勾选“虚拟机平台”并确定。

      3、接着我们去系统设置中将区域更改为“美国”

      4、修改完成后进入微软商店,下载“Windows Subsystem for Android™ 。..。.”应用。

      5、下载完成后打开该软件。

      6、根据提示完成设置,进入以下界面后就可以关闭了。

      7、然后我们点开开始菜单,搜索“Android”,打开最佳匹配的设置。

      8、在其中开启开发人员模式,确认已连接到ADB。保存ADB前的地址。

      9、然后我们打开“windows powershell”,

      在其中输入“adb connect 127.0.0.1:58526(这里的数字填写自己电脑的端口)”。

      10、接着输入“adb install 。/coolapk.apk”(这里的coolapk.apk是我们准备的安卓安装包,也是填自己想要安装的应用程序名称)

      11、最后软件就会自动为你安装安卓应用了,安装完成后即可在win11中运行安卓app。

      12、另外,只有最新的win11才可以使用这个功能,所以大家要使用的话需要更新最新win11。【点击下载

  • 无法访问 Github ?

    该脚本只能提高 Github 文件下载速度,但是大家可能发现了自从 2021 年 3 月初某会开始,很多地区已经间歇性无法访问 Github 了。
    这种情况无论是改 DNS 还是改 Hosts 都没用,因为是蔷对 Github 域名 SNI 干扰/封锁,任意 IP 指向 Github 去访问时,该 IP 的 443 端口就会超时 3 分钟!
    因为是随机干扰的,所以有时候会碰到 “短暂” 可用的 IP(模拟丢包、伪装为网站自身网络问题)。

    有兴趣可以看看这篇详细讲解分析的文章: https://www.v2ex.com/t/758568

    因此目前只有三种方法可以访问 Github 了:

    1. 梯子
    2. 镜像站( https://kgithub.com / https://hub.fgit.gq / https://hub.fgit.ml / 访问 Github 自动重定向至镜像站的方法
    3. 肉身出国
    4. 本地代理直连加速,绕过 SNI 干扰( https://github.com/docmirror/dev-sidecar / https://gitee.com/docmirror/dev-sidecar )
  • TVBOX 接口配置

    TVbox在线接口:https://tv.203511.xyz/0821.json

    版本
    1.开源版 自用https://raw.liucn.cc/box/m.json https://raw.iqiq.io/liu673cn/box/main/m.json
    ?官方原版TVBox_q215613905_20230302-0924.apk ?UI美化版TVBox_takagen99_20230527-1118.apk 
    ?更多TVbox ?更多TVbox ?更多下载 ?更多下载 ?Pluto Player 
    2.多仓版 他人整理https://raw.liucn.cc/box/dm.txt https://raw.iqiq.io/liu673cn/box/main/dm.txt
    ?原版影视仓V3-3.0.32.apk ?原版影视仓4.0.32_1.apk
    ?UI改版可视TVMax_1.6.4.apk ?更多 ?更多
    3.内置版
    ?苹果_4.4.apk 魔改版

    https://jihulab.com/duomv/apps/-/raw/main/fast.json