首页 文章 精选 留言 我的

精选列表

搜索[学习],共10000篇文章
优秀的个人博客,低调大师

Ansible yaml的语法、playbook文件例子(学习笔记十七)

1、ansible有两种调用方式,一种是临时语句,一种是yml文件调用,语法格式分别为: ansible all -m ping ansible-playbook test.yml 2、test.yml为yaml文件,yaml使用空白、缩进、分行组织数据。 3、yaml有如下几个基本规则: ·大小写敏感 ·缩进表示层级关系 ·禁止使用tab键 ·缩进长度没有限制,只要元素对齐就表示 这些元素属于一个层级 ·#号注释 4、yaml的数据结构有如下规则: ·使用冒号(:)表示键值对: age:12 name:huang ·使用连字符(-)表示数组: -a -b -c 5、复合使用的例子: languages: - Ruby - Perl - Python websites: YAML: yaml.org Ruby: ruby-lang.org Python: python.org Perl: use.perl.org 6、 test.yml --- - hosts: webservers gather_facts: false tasks: - name: chattr -i shell: chattr -i /etc/shadow - name: copy ssh key shell: echo 'xxxxxxxxx' |passwd --stdin root - name: chattr +i shell: chattr +i /etc/shadow hosts表示主机群组,gather_facts表示是否获取主机的信息,空格间的对齐必须严格,每个name代表一个任务,如果中间某个任务出错,下面的任务不会继续执行。

优秀的个人博客,低调大师

深入java虚拟机学习 -- 内存管理机制

前面说过了类的加载机制,里面讲到了类的初始化中时用到了一部分内存管理的知识,这里让我们来看下Java虚拟机是如何管理内存的。 先让我们来看张图 有些文章中对线程隔离区还称之为线程独占区,其实是一个意思了。下面让我们来详细介绍下这五部分; 运行时数据区 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域,这些区域都拥有自己的用途,并随着JVM进程的启动或者用户线程的启动和结束建立和销毁。 先让我们了解下进程和线程的区别: 进程是资源分配的最小单位,线程是程序执行的最小单位。 进程有自己的独立地址空间,每启动一个进程,系统就会为它分配一个地址空间、建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。而线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费要比进程小很多,同时创建一个线程的开销也要比进程小很多。 同一个进程中可以包括多个线程,并且线程共享整个进程的资源(寄存器、堆栈、上下文),一个进程至少包含一个线程。线程之间的通信更加方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信则需要以通信的方式(IPC)进行。 这里引用在知乎中某位同学的解释, 进程的颗粒度太大,每次都要有上下的调入,保存,调出。如果我们把进程比喻为一个运行在电脑上的软件,那么一个软件的执行不可能是一条逻辑执行的,必定有多个分支和多个程序段,就好比要实现程序A,实际分成 a,b,c等多个块组合而成。那么这里具体的执行就可能变成: 程序A得到CPU =》CPU加载上下文,开始执行程序A的a小段,然后执行A的b小段,然后再执行A的c小段,最后CPU保存A的上下文。 这里a,b,c的执行是共享了A的上下文,CPU在执行的时候没有进行上下文切换的。 看到这里是不是对线程共享和线程隔离区有了一个更深次的理解。可以理解为方法区和堆是分配给进程的,也就是线程共享区,而栈和程序计数器则是分配给每个独立线程的。 在SUN公司的HotSpot虚拟机中将java虚拟机栈和本地方法栈合二为一了 程序计数器(Program Counter Register) 程序计数器(Program Counter Register)是一块较小的内存空间,它可以看成是当前线程所执行字节码的行号指示器。在计算机中,其实程序计数器就是一个寄存器,依据不同计算机细节的差异,它可以存放当前正在被执行的指令,也可以放下一个被执行的指令。 在虚拟机的概念模型中,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令的。 由于Java虚拟机的多线程是通过线程轮询切换并分配处理器执行时间的方式来实现的,在任何一个确定的时候,一个处理器都只会执行一条线程中的指令,因此为了线程切换之后能过恢复到正确的执行位置,每条线程都需要拥有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,所以程序计数器是线程私有的内存,也就是它属于线程隔离区的。 如果线程执行的是一个Java方法,这个计数器记录的就是正在执行的虚拟机字节码指令地址;如果正在执行的是Native方法,那么这个计数器的值就是(Undefined)。 此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。 Java虚拟机栈 Java虚拟机栈(Java Virtual Machine Stack)也是线程私有的,即他的生命周期和线程相同。 在Java中,JVM中的栈记录了线程的方法调用,每个线程拥有一个栈,在某个线程的运行过程中,如果有新的方法调用,那么该线程对应的栈就会增加一个存储单元,即栈针(Stack Frame)。 虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行时都会创建一个栈针(Stack Frame)用于存储局部变量表、操作数栈、动态连接、方法出口等信息。每一个方法从调用至完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。 当被调用方法运行结束时,该方法对应的帧将被删除,参数和局部变量所占据的空间也随之释放。线程回到原方法,继续执行。当所有的栈都清空时,程序也随之运行结束。 我们经常说的栈内存其实就是现在讲的虚拟机栈,或者说是虚拟机栈中局部变量表部分。 局部变量表存放了编译器可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,它不等同于对象本身,可能是指向对象起始位置的引用指针,也可能是指向一个代表对象的句柄或其他与此对象相关的位置,引用所指向的对象保存在堆中(引用可能为Null,即不指向任何对象))和returnAddress类型(指向了一条字节码指令的地址)。 其中64位长度的long和double类型的数据会占用2个局部变量空间(Slot),其余数据类型只占用1个。局部变量表所需要的内存空间在编译时期完成分配。当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。 异常有两种 1,线程请求的栈深度大于虚拟机所允许的深度将抛出StackOverflowError异常 (递归调用) 2,如果虚拟机可以动态扩展,如果扩展时已经无法申请到足够的内存就会抛出OutOfMemeoryError异常。 List list=new ArrayList(); for(;;){ int[] tmp=new int[1000000]; list.add(tmp); } 本地方法栈 本地方法栈(Native Method Stack)与虚拟机栈所发挥的作用是非常相似的。他们之间的区别就是Java虚拟机栈是位虚拟机执行Java方法(也就是字节码)服务,而本地方法栈为位虚拟机使用到的Native方法服务。 其实虚拟机规范中对本地方发栈中方法所使用的语言、使用方式以及数据结构都没有强制规定,因此具体的虚拟机可以自由地实现它。甚至在有的虚拟机(如Sun HotSpot虚拟机)直接就把本地方法栈和虚拟机栈合二为一。与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemory异常。 Java堆 对于大多数应用来说,Java堆(Java Heap)是Java虚拟机管理的内存中最大的一块。 Java堆是被所有线程共享的一块数据区域,在虚拟机启动时创建,这一内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。 但是随着JIT编译器的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化发生,所有的对象都分配在堆上也逐渐变得不是那么“绝对”。 堆中可细分为新生代和老年代,在细分可以分为Eden空间、Form Survivor空间、to Survivor空间。 Java堆是垃圾收集器管理的主要区域,因此很多时候也被称为“GC堆”。 根据Java虚拟机规范规定,Java堆可以处于物理上不连续的内存中,即只要逻辑上是连续的即可,就像我们的磁盘空间一样。在实现时,可以固定大小也是可扩展的。主流的虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms来控制)。如果在堆中没有内存可分配,并且堆也无法继续扩展时,将会抛出OutOfMemortError异常。 Java的普通对象存活在堆中,与栈不同,堆的空间不会随着方法调用结束而清空。因此,在某个方法中创建的对象,可以在方法调用结束之后,继续存在堆中。这带来的一个问题是,如果我们不断的创建新的对象,内存控件将会最终消耗殆尽。 方法区 方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译之后的代码等数据。虽然Java虚拟机将其描述为堆的一个逻辑部分,但它却有一个别名叫做Non-Heap(非堆)。目的是与Java堆区分开来。(以前很多人把方法区称为永久代,现在JDK1.8中已经用元数据区域取代了永久代)。 运行时常量池 运行时常量池(Runtime Constant Pool)是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池。用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入到方法区的运行时常量池中存放。并非预置入Class文件中常量池的内容才进入方法运行时常量池,运行期间也可能将新的常量放入池中,这种特性被开发人员利用得比较多的便是String类的intern()方法。 public class Test { public static void main(String[] args) { String s1="hello china";//字节码常量 String s2="hello china"; String s3=new String("hello china"); System.out.println(s1 == s2); System.out.println(s1 == s3); System.out.println(s1 == s3.intern());//运行时常量 intern 是个native方法 } } 当方法区无法满足内存分配需求时,抛出OutOfMemoryError 注:JDK8之前,方法区由永久代实现,主要存放类的信息、常量池、方法数据、方法代码等;JDK8之后,取消了永久代,提出了元空间,并且常量池、静态成员变量等迁移到了堆中;元空间不在虚拟机内存中,而是放在本地内存中。 直接内存 由于直接内存(Direct Memory)并不是java虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,但是这部分也被频繁使用,而且也可能导致内存溢出异常出现,所以也放到这一部分进行简介。 先让,本机直接内存的分配不会受到Java堆大小的限制,但是肯定还是会受到本机总内存大小以及处理器寻址空间的限制。管理员在配置虚拟机参数时,会根据实际内存设置-Xmx等参数信息,但经常会忽略直接内存,使得各个内存区域总和大于物理内存限制(包含物理的和操作系统级的限制),从而导致动态扩展时出现OutOfMemoryError异常。 JDK1.4加入了NIO,引入一种基于通道与缓冲区的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。因此避免了在Java堆和Native堆中来回复制数据,提高了性能。 Object obj = new Object(); Object obj将会反映到虚拟机栈中(reference类型)new Object()将会反映到Java堆中此类的对象类型、父类、实现的接口、方法等信息数据,将反映到方法区中开开心心编码,快快乐乐生活。

优秀的个人博客,低调大师

php代码审计分段学习(php_bug)[3]

参考:https://github.com/bowu678/php_bugs 21.数字验证正则绕过 0 >= preg_match('/^[[:graph:]]{12,}$/', $password)//输入的内容必须为12个以上,不包括空格和tab键 $reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/'; //[[:punct:]] 任何标点符号, [[:digit:]] 任何数字, [[:upper:]] 任何大写字母 , [[:lower:]] 任何小写字母 if (6 > preg_match_all($reg, $password, $arr)) //匹配到的次数要大于6次才能绕过。连续的大写或小写字母都只能算是一次。 $ps = array('punct', 'digit', 'upper', 'lower'); foreach ($ps as $pt) { if (preg_match("/[[:$pt:]]+/", $password)) $c += 1; } if ($c < 3) break;//必须要有大小写字母,数字,字符内容三种与三种以上 "42" == $password//最后输入的内容还得和42相等。 可以构造420.000000e-1//0可以随意添加不影响数值,但是要超过12个字符 22.弱类型整数大小比较绕过 is_numeric($temp)?die("no numeric"):NULL; //若是纯数字则会返回为no numeric $temp>1336//但是要是想得到flag还得比1336大,尝试构建13e4,但是整数、小数、指数表示以及16进制数值都会通过判断。 当一个整形和一个其他类型行比较的时候,会先把其他类型intval再比。若输入13e4a,在is_numeric中返回true,然后在比较时被转换成数字130000,成功实现 23.md5函数验证绕过 md5($temp)==0//这个很好绕过,md5后的值和0相等就行了 ①.输入的值为空 ②.有这种md5('240610708')后的值为0e开头的就行 ③.类似md5('1')值开头为字母的也能通过 24 md5函数true绕过注入 $sql = "SELECT * FROM users WHERE password = '".md5($password,true)."'"; 存在这个条件md5($password,true) 当md5后的hex转换成字符串后,如果包含 'or'<trash> 这样的字符串,那整个sql变成 SELECT * FROM admin WHERE pass = ' ' or '6<trash>' 就绕过了 字符串:ffifdyop,md5后,276f722736c95d99e921722cf9ed621c hex转换成字符串:'or'6<trash> 25.switch没有break 字符与0比较绕过 case 0: case 1: case 2: require_once $which.'.php'; echo $flag;break; default: echo GWF_HTML::error('PHP-0817', 'Hacker NoNoNo!', false);break; 学c语言的时候,对于switch的理解就是若是前几个case语句只有一个输出条件,并且只有一个break的话,就是前几个case语句共用这一个输出条件,只要满足其中一个case语句就会输出,看了大佬的wp,嗯好像理解差不多,就是若是第一个case若是判断成功,就算没有break,后面的也不会再判断了,直接到2的时候,输出require_once这个包含文件,若是$flag在那个文件中就输出了。http://localhost/php_bug/25.php?which=flag,嗯输出了我flag.php中的东西。 26.unserialize()反序列化 1.png 2.png 3.png flag在pctf.php,但showimg.php中不允许直接读取pctf.php,只有在index.php中可以传入变量class ,index.php中Shield类的实例$X = unserialize($g),$g = $_GET['class'];,$X中不知$filename变量,但需要找的是:$filename = "pctf.php",现$X已知,求传入的class变量值。 可以进行序列化操作: 运行index.php得到O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";},提交就行了 2.png 这段代码的要求是提交a,b,c满足要求才能得到flag。首先id不能为0,但是下面的语句$id==0,可以利用弱类型让id=0a就可以了;a的话是打开名为a的文件内容为1112 is a nice lab!,但是stripos($a,'.')这个又把文件包含给过滤了,看大佬们用到了php://input,在post里面提交1112 is a nice lab!就行了;b的话是长度大于5且b[0]!=4,且’1114’中存在’111’+b[0]。Strlen检测长度时遇到%00不会被截断,而eregi会被截断,故构造b为字串,首位为%00,长度大于5,则检测时长度满足,eregi(‘111’,’1114’)也满足,b首位整形也不等于4也满足,即可得到flaghttp://localhost/php_bug/27.php?id=0a&a=php://input&b=%0011111在火狐的post框框里面加上1112 is a nice lab!就i可以了。 1.png 题目链接:web.jarvisoj.com:32778/ 这个题目是源码泄露,在网址后面加上index.php~,下载下来然后改名字index.php.swp,在虚拟机里面打开,vim -r index.php.swp 但是在保存的时候出现了E212问题,嗯直接看大佬博客就行了,https://www.jianshu.com/p/3e5a9be54d8f,嗯源码贴下。 1.png 要想成功拿到flag,需要满足$role==="admin" && $hsh === md5($salt.strrev($_COOKIE["role"])) 这个地方用到了哈希长度扩展攻击,它的原理是 https://github.com/iagox86/hash_extender,这个解释的很详细,直接看这个就行了 我们可以在不知道salt是什么的情况下生成签名!我们将字符串与我们的新签名一起发送到服务器。服务器将预先签名,散列它,并提出与我们完全相同的散列 可以直接用hashpump这个工具,安装方式如下 git clone https://github.com/bwall/HashPump apt-get install g++ libssl-dev cd HashPump make make install salt的长度不知道,但是我们可以尝试啊, 1.png 最后将role这个数据反一下提交,就出来flag了。 1.png 2.png 这个是题目的链接:http://web.jarvisoj.com:32794 闭合,查用户名:?table=flag union select user() limit 1,1 查表:?table=flag``union select group_concat(table_name) from information_schema.tables where table_schema=database() limit 1,1 查列:?table=flag union select group_concat(column_name) from information_schema.columns where table_name=0x7365637265745f666c6167 limit 1,1 查flag:?table=flag `union select flagUwillNeverKnow from secret_flag limit 1,1 30.利用提交数组绕过逻辑 2.png 总觉得这段代码在哪里见过,但是就是找不到原题目了。先看代码, $role = unserialize(base64_decode($_COOKIE["role"]));嗯把cookie解码并反序列化后是admin才能继续往下做,但是role本身给的值是guest,将生成的cookie拿去base64解码,然后将里面的guest改为admin再提交,就成功绕过了第一步;,然后就是post提交filename数据和data数据,前者没什么可以利用的,但是后者就比较难受了首先(preg_match('[<>?]', $data),提交的数据中不能出现<>,但是在 $s = implode($data);if(!preg_match('[<>?]', $s)){$flag='None.';},这时候又需要有<>,想要通过Post请求的形式传入数组可以使用 data[0]=123&data[1]=<> 的形式传入数组,这样的话在执行 implode() 函数的时候就不会使 &s 为空,成功绕过这段逻辑拿到flag。

优秀的个人博客,低调大师

Step by step,学习EMR集群的fair类型资源池

集群越大,跑的业务越多,越需要资源池管理。资源调度是yarn的核心。 EMR现在支持在业务视角操作yarn资源池了,资源池文档介绍了如何使用。 企业用户往往会选择使用fair调度类型的资源池。本文以一家大数据分析公司业务发展为故事背景,一步步的介绍如何使用fair调度。fair调度详细参数信息可参见官方文档 一个数据分析师 公司刚开始,业务团队只有小明一个数据分析师。一个人用整个集群,默认资源池配置即可。随便跑作业,随便杀作业。 三个数据分析师 公司发展,业务团队小明,张华,李萍三个数据分析师了。还用默认资源池不分队列,一个人把资源用满其他人就用不了了。杀作业很容易杀掉别人的作业,互相影响,出了问题无法定位。 于是采用三个人均分资源策略,创建三个资源池,只设置名字和权重1,管理访问控制的用户名。放置策略采用用户名为队列。gateway上建了三个

优秀的个人博客,低调大师

php代码审计分段学习(php_bug)[2]

参考:https://github.com/bowu678/php_bugs 11.sql闭合绕过 $sql = "select user from php where (user='$user') and (pw='$pass')";嗯好吧这个不就是sqli-labs的Less-3么,放下writeup好了http://localhost/php_bug/11.php/?user=admin')# 12.X-Forwarded-For绕过指定IP地址 if ($GetIPs=="1.1.1.1"){ echo "Great! Key is *********";},直接bp抓包,在http头里面加上X-Forwarded-For:1.1.1.1就行了,X-Forwarded-For代表客户端,里面存放的是HTTP端请求的真实ip。 13.md5加密相等绕过 $a != 'QNKCDZO' && $md51 == $md52,两个字符串不相等但是md5后的值相等,记下writeup。 var_dump(md5('240610708') == md5('QNKCDZO'));//ture var_dump(md5('aabg7XSs') == md5('aabC9RqS'));//ture var_dump(sha1('aaroZmOk') == sha1('aaK1STfY'));//ture var_dump(sha1('aaO8zKZF') == sha1('aa3OFF9m'));//ture var_dump('0010e2' == '1e3');//ture var_dump('0x1234Ab' == '1193131');//ture var_dump('0xABCdef' == ' 0xABCdef');//ture ==对比的时候会进行数据转换,0eXXXXXXXXX就成0了,如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换为数值并且比较按照数值来进行,嗯还是用===好一些,尽量不要用==。 14.intval函数四舍五入 emmmm,这个函数。。。先是查询的时候intval($_GET['id'])为1024,但是$_GET['id']又不能为1024,直接1024.325加个小数点就行了。。intval会自动将小数点后面的数值舍掉 15 strpos数组绕过NULL与ereg正则%00截断 @ereg ("^[1-9]+$", $_GET['nctf'] strpos ($_GET['nctf'], '#biubiubiu') ①.这个是要求输入的内容必须为纯数字,但是还有出现#biubiubiu的内容,eregde%00截断可以实现,但是题目上给的#需要url编码一下,要不实现不了。http://localhost/php_bug/15.php?nctf=12414%00%23biubiubiu ②.strpos()找的是字符串,那么传一个数组给它,strpos()出错返回null,null!==false,符合要求. 所以输入nctf[]= ,ereg()在出错时返回的也是null,null!==falsehttp://localhost/php_bug/15.php?nctf[]= 16.SQL注入or绕过 $query='SELECT * FROM interest WHERE uname=''.$username.'' AND pwd=''.$password.'';'; $query='SELECT * FROM users WHERE name=''admin'' AND pass=''or 1 #'';'; ?username=admin'' AND pass=''or 1 #&password= 有点传说中的花式闭合的感觉。。 17.密码md5比较绕过 总感觉眼熟,emmm和第九个是一样的。。。 ?user=' union select '202cb962ac59075b964b07152d234b70' #&pass=123 18.md5()函数===使用数组绕过 $_GET['username'] == $_GET['password'] md5($_GET['username']) === md5($_GET['password'])http://localhost/php_bug/18.php?username[]=1&password[]=2,前面已经在sha1()函数比较绕过这个里面详细说过了,,基本同样道理,这里就不多做描述了。 19 ereg()函数strpos() 函数用数组返回NULL绕过 ereg ("^[a-zA-Z0-9]+$", $_GET['password']) strpos ($_GET['password'], '--') emm这个和15是一样的只是ereg()的这个函数现在要求的是只能出现字母和数字,依旧是两种方法http://localhost/php_bug/19.php?password[]=http://localhost/php_bug/19.php?password=12a%00-- 十六进制与数字比较 ($digit >= $one) && ($digit <= $nine) $number == $temp 这个题的要求是输入的数字不能是1~9的数字,但是又要与3735929054相等,转化为16进制http://localhost/php_bug/20.php?password=0xdeadc0de 54975581388转换成16进制为ccccccccc

优秀的个人博客,低调大师

标准模板库(STL)学习指南之set集合

set是关联容器。其键值就是实值,实值就是键值,不可以有重复,所以我们不能通过set的迭代器来改变set的元素的值,set拥有和list相同的特性:当对他进行插入和删除操作的时候,操作之前的迭代器依然有效。当然删除了的那个就没效了。set的底层结构是RB-tree,所以是有序的。 stl中特别提供了一种针对set的操作的算法:交集set_intersection,并集set_union,差集set_difference。对称差集set_symeetric_difference,这些算法稍后会讲到。 一:set模板类的声明。 template < class key class =Traitsless<key> class Allocator=allocator<key> > class set。 其中个参数的意义如下: key:要放入set里的数据类型,可以是任何类型的数据。 Traits:这是一个仿函数(关于仿函数是什么,我后面的文章会讲到)。提供了具有比较功能的仿函数,来觉得元素在set里的排列的顺序,这是一个可选的参数,默认的是std::less<key>,如果要自己提供这个参数,那么必须要遵循此规则:具有两个参数,返回类型为bool。 Allocator:空间配置器,这个参数是可选的,默认的是std::allocator<key>. 二:set里的基本操作 我们可以通过下面的方法来实例化一个set对象 std::set<int> s;那个s这个对象里面存贮的元素是从小到大排序的,(因为用std::less作为比较工具。) 如果要想在s里面插入数据,可以用inset函数(set没用重载[]操作,因为set本生的值和索引是相同的) s.insert(3);s.insert(5)..... 因为set是集合,那么集合本身就要求是唯一性,所以如果要像set里面插入数据和以前的数据有重合,那么插入不成功。 可以通过下面的方法来遍历set里面的元素 1 2 3 4 5 std::set< int >::iterator it = s.begin(); while (it!=s.end()) { cout<<*it++<<endl; //迭代器依次后移,直到末尾。 } 如果要查找一个元素用find函数,it = s.find(3);这样it是指向3的那个元素的。可以通过rbegin,rend来逆向遍历 1 2 3 4 5 std::set< int >::reverse_iterator it = s.rbegin(); while (it!=s.rend()) { cout<<*it++<<endl; } 还有其他的一些操作在这就不一一列出了。 三:set向量的使用实例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 #include <iostream> #include <string> #include <set> #include <algorithm> #include <iterator> using namespace std; /* 联合容器将值与关键字联合在一起,使用关键字来查找值, * 提供元素的快速访问,插入元素不能指定位置,容器自动处理插入位置 * STL 提供四种联合容器:set、multiset、map、multimap * set、multiset 存储一种元素,前者关键字不可重复,后者关键字可以重复。 * map、multimap 存储一对元素键与值,前者关键字不可重复,后者关键字可以重复。 */ int main() { const int N = 3; string s1[N] = { "xp" , "python" , "linux" }; string s2[N] = { "python" , "php" , "perl" }; set<string> sa(s1, s1 + N); // 声明一个集合sa,元素为数组s1 set<string> sb(s2, s2 + N); // 声明一个集合sb,元素为数组s2 set<string> sc; // 声明一个空集合sc ostream_iterator<string, char > out (cout, " " ); copy(sa.begin(), sa.end(), out); cout << "->set sa" << endl; copy(sb.begin(), sb.end(), out); cout << "->set sb" << endl; set_union(sa.begin(), sa.end(), sb.begin(), sb.end(), out); cout << "->set_union() 并集" << endl; set_intersection(sa.begin(), sa.end(), sb.begin(), sb.end(), out); cout << "->set_intersection() 交集" << endl; set_difference(sa.begin(), sa.end(), sb.begin(), sb.end(), out); cout << "->set_difference() 集合的差" << endl; set_difference(sb.begin(), sb.end(), sa.begin(), sa.end(), out); cout << "->set_difference() 集合的差" << endl; set_union(sa.begin(), sa.end(), sb.begin(), sb.end(), insert_iterator<set<string> >(sc, sc.begin() )); sc.insert( "delphi" ); copy(sc.begin(), sc.end(), out); cout << "->set sc" << endl; copy(sc.lower_bound( "perl" ), sc.upper_bound( "python" ), out); cout << "->显示集合区间" << endl; return 0; } 作者:ACShiryu出处:http://www.cnblogs.com/ACShiryu/若非注明,本博客文章均为原创,版权归作者和博客园共有,欢迎转载,但必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。该文章也同步发布在我的新浪微博中-ACShiryu's weibo,欢迎收听。

优秀的个人博客,低调大师

php代码审计分段学习(php_bug)[1]

参考:https://github.com/bowu678/php_bugs 1.extract变量覆盖 看extract变量覆盖这个的时候,代码里面出现了trim这个函数,就查了一下用法,说是去掉字符串开头和结尾的换行符或者是空格,还可以去掉不想出现的字符串。要说起来这个函数还是挺好理解的。就比如说最后一个吧,heordw,先从首开始看,到l的时候想去掉的字符串里面没有,所以到l的时候不再去掉任何字符,然后从尾往前看,是和首同样的道理 $str="helloeorldhelloworld"; echo trim($str,"herl");//oeorldhelloworld echo trim($str,"heorld");//w $str="helloeorlwdhelloworod"; echo trim($str,"heordw");//lloeorlwdhell file_get_contents($flag)//若是$flag的内容为字符串直接返回为空,若是txt的话能打开里面的内容。 extract($_GET)这个函数可以判断是get提交还是post提交,当为get提交时可以url中可以这样使用http://localhost/php/extract1.php?flag&shiyan #flag和shiyan是php中的两个变量。在extract()中,若是在url中有给变量赋值,则原本这个变量的值会被替换。可以预防被覆盖的方法是在php.ini这个文件中有register_globals这个变量的话将它改为off就行了,可能php版本问题,我的文件中没有这个变量。。。可能这个bug还是挺有用的。。 2.绕过过滤的空白字符 首先is_numeric这个函数要求的是为数字字符串,所以要想跳过这个函数可以加字母或者加一些编码后的符号。 然后$req['number']==strval(intval($req['number']))这个是要求输入的字符串取整和原本字符串相等,但是取整的时候若是有字母或是特殊字符直接截断了,若是构造这个数字100.000000000000010可以跳过这个函数,但是最开始的条件就跳不过了,若是在后面加上字母什么的可以跳过第一个,但是传入的字符串是存到数组中的,所以自己不会发生溢出情况。 $number[$i] !== $number[$j],后面的这个函数就容易实现了%00%0c191,%0c是\f的转义字符,%00的ascii值是0,后面的数字可以任意写,%00为截断,不能省略。 3.多重加密 这是题目给的加密方式 这是根据题目写出的解密方式 4.SQL注入_WITH ROLLUP绕过(实验吧 因缺思汀的绕过) $filter = "and|select|from|where|union|join|sleep|benchmark|,|\(|\)";这个是不能使用的单词。 mysql_num_rows($query) == 1//这个是要求函数返回结果集中行的数目必须为1 $key['pwd'] == $_POST['pwd']这个则是要求了提交的密码与数据库中的密码相等才能输出flag 当用rollup这个语句的时候,会在数据库的最后一行生成一个密码为NULL的字段 用下面这个payload ' or 1=1 group by pwd with rollup limit 1 offset 2 # 这样查询语句就会变成 SELECT * FROM interest WHERE uname = ' ' or 1=1 group by pwd with rollup limit 1 offset 2 # group by pwd with rollup 这个可以在数据库中添加一行pwd为NULL的数据,limit 1是之查询一行,offset 2这个数字可以换,不同的数字出现的是不同行的内容。 5.ereg正则%00截断 ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE //这个函数要求输入的密码只能是大小写字母和数字 strlen($_GET['password']) < 8 && $_GET['password'] > 9999999这个要求了输入的密码长度小于8但是还得大于9999999,可以使用科学计数法表示,计算器或电脑表达10的的幂是一般是e strpos ($_GET['password'], '*-*') !== FALSE,strpos函数是查找后面的字符串在前面的字符串出现的位置,所以输入的密码中还得有*-*,但是前面的ereg函数过滤了特殊字符,这时候可以用ereg%00截断这个bug,ereg读到%00的时候,就截止了,所以1e9%00*-*就可以。 6.strcmp比较字符串 strcmp($_GET['a'], $flag) == 0// 参数 str1第一个字符串。str2第二个字符串。如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;只有两者相等,才返回 0。 strcmp只会处理字符串参数,如果给个数组的话,就会返回NULL,而判断使用是==,NULL==0是bool(true),所以构造这个函数a[]=1就行了。 7.sha1()函数比较绕过 $_GET['name'] == $_GET['password'])//若是传入的两个参数不同才能绕过这个函数 sha1($_GET['name']) === sha1($_GET['password']) sha1()函数默认的传入参数类型是字符串型,要是给它传入数组会出现错误,使sha1()函数返回错误,也就是返回false,这样一来===运算符就可以发挥作用了,需要构造username和password既不相等,又同样是数组类型 构造?name[]=1&password[]=12这样可以绕过 8.SESSION验证绕过 $_GET['password'] == $_SESSION['password']//在这个函数中,需要让提交的密码和session这个相等 ?password=这样构建并把cookie清空,刚开始我以为isset会把这个空的过滤掉,但虽然是空也没过滤。 9.密码md5比较绕过$pass = md5($_POST[pass]); $row = mysql_fetch_array($query, MYSQL_ASSOC); ($row[pw]) && (!strcasecmp($pass, $row[pw]))//这个就是构建一个数值和它的md5密码值 ?user=' union select '202cb962ac59075b964b07152d234b70' #&pass=123 10.urldecode二次编码绕过 eregi("hackerDJ",$_GET['id'] $_GET[id] = urldecode($_GET['id']); $_GET[id] == "hackerDJ" 这段代码是首先先匹配输入的值是否和hackerDJ相等,若是不等才可以继续下面的解码再让相等才可以,所以直接其中的一个字母编码两次就可以了。不知道为什么在php代码或者找的网站中都不能编码只能解码,所以看了原题目的wp。。不知道什么原因就是不能编码有点难受。。 http://localhost/php_bug/10.php/?id=%2568ackerDJ

优秀的个人博客,低调大师

HBase学习&实践笔记之HBase初探(to be continued...)

HBase初探 To be continued... HBase架构 HBASE的逻辑&物理存储结构 启动HBase HBase version: 1.2.6 Hadoop version: 3.0.0 伪分布式启动 hbasedir/conf/hbase-env.xml配好JAVA_HOME。 export JAVA_HOME=$(/usr/libexec/java_home) 我做了几个系统宏,方便命令执行。 alias starthbase='sudo /Users/fujianbo/Applications/hbase-1.2.6/bin/start-hbase.sh' alias stophbase='sudo /Users/fujianbo/Applications/hbase-1.2.6/bin/stop-hbase.sh' alias startresthbase='sudo /Users/fujianbo/Applications/hbase-1.2.6/bin/hbase rest start' alias hbaseshell='sudo /Users/fujianbo/Applications/hbase-1.2.6/bin/hbase shell' 伪分布式启动下,不需要开启zookeeper相关配置,否则在启动hbase控制台时会报错: ERROR [main] zookeeper.RecoverableZooKeeper: ZooKeeper exists failed after {N} attempts 分布式启动 DDL: 在控制台执行 Let's move! starthbase -> hbaseshell, 启动hbase并进入hbase控制台。 使用"put 'user','row1','info:name','jianbo'"命令往user表里插入一条rowkey='row1', value='jianbo'的纪录: 对于同一个rowkey,第二次put操作被认为是更新操作: 使用"get [tablename],[rowkey],[column family]"命令查询数据: 使用"disable [tablename]"命令失效表(注:非物理删除),表失效后已不能新增或者查询数据。 使用"enable [tablename]"生效已被失效的表,"drop [tablename]"物理删除表。 使用"describe [tablename]"查看表结构。 使用list命令查看"本地"数据库信息: 使用"scan [tablename]"全表扫描数据: 使用"deleteall [tablename],[rowkey]"删除整行数据: 使用"truncate [tablename]"删除指定表的所有数据: 其他系统命令 【查看连接hbase的用户信息】whoami

优秀的个人博客,低调大师

大数据学习笔记(二):Hadoop2.x概述

什么是Hadoop 开源的 可靠的:可以通过备份的数据恢复 可扩展:机器动态的增加或减少不会影响数据的存储和计算 分布式计算:多台机器并行的处理 Hadoop能做什么 海量数据的存储——HDFS 存储海量数据 动态的添加机器 备份 当数据收到损坏时,快速自动恢复 海量数据分析——mapreduce 核心理念:分而治之 处理海量的数据获得有价值的信息 mapreduce原理: 假设有海量的数据要我们来数其中各个图形的数目,我们可以简化一下,如上图,要数左边的个数,可以分给两个计算机去处理,最后何总得到结果。同样的,如果有大量数据,就可以分给百台计算机去处理。 任务调度和集群资源管理——YARN 资源管理(cpu,内存) 通过资源管理来合理安排任务,进行任务调度 Hadoop特点 扩容能力:动态增加或减少,并不会影响集群计算 成本低:普通的机器也能作为集群的结点 高效率:分布式计算 可靠性:默认备份三份,也可以指定备份多少 应用场景 日志分析:公司的每天产生的日志分析 推荐系统:淘宝购买物品之后,分析你的购物,推荐物品 来看一下课程中给的一张图:

优秀的个人博客,低调大师

深入java虚拟机学习 -- 类的加载机制

当看到“类的加载机制”,肯定很多人都在想我平时也不接触啊,工作中无非就是写代码,不会了可以百度,至于类,jvm是怎么加载的我一点也不需要关心。在我刚开始工作的时候也觉得这些底层的内容距离我还很遥远,根本不用关系,可是随着做开发的时间越来越长,慢慢的已经意识到虚拟机相关要领的重要性。一直想写篇和虚拟机相关的文章,无奈之前由于各种原因一直没写,年初工作还不是很忙,抽时间来慢慢完善jvm的内容。 好了,不说废话了,大家一起来看下代码吧,都来猜猜下面的两份代码的执行结果是什么? 1 class Singleton 2 { 3 private static Singleton singleton = new Singleton(); 4 public static int counter1; 5 public static int counter2=0; 6 7 private Singleton(){ 8 counter1++; 9 counter2++; 10 } 11 12 public static Singleton getInstance(){ 13 return singleton; 14 } 15 } 16 17 public class Demo 18 { 19 public static void main(String[] args){ 20 Singleton singleton=Singleton.getInstance(); 21 System.out.println("counter1:"+singleton.counter1); 22 System.out.println("counter2:"+singleton.counter2); 23 } 24 } 1 class Singleton 2 { 3 public static int counter1; 4 public static int counter2=0; 5 private static Singleton singleton = new Singleton(); 6 7 private Singleton(){ 8 counter1++; 9 counter2++; 10 } 11 12 public static Singleton getInstance(){ 13 return singleton; 14 } 15 } 16 17 public class Demo 18 { 19 public static void main(String[] args){ 20 Singleton singleton=Singleton.getInstance(); 21 System.out.println("counter1:"+singleton.counter1); 22 System.out.println("counter2:"+singleton.counter2); 23 } 24 } 看到这样的结果,不知道你有没有意外呢?看完我的这几篇文章后聪明的你一看就明白是怎么回事了。 java虚拟机与程序的生命周期 -执行了System.exit()方法 - 程序正常执行结束 -程序在执行过程中遇到了异常或错误而终止 -由于操作系统出现错误导致java虚拟机进程终止 在如上几种情况下,java虚拟机将结束自己的生命周期 类的生命周期 类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)7个阶段。其中准备、验证、解析3个部分统称为连接(Linking)。如图所示。 加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的,类的加载过程必须按照这种顺序按部就班地开始,而解析阶段则不一定:它在某些情况下可以在初始化阶段之后再开始,这是为了支持Java语言的运行时绑定(也称为动态绑定或晚期绑定)。 加载 查找并加载类的二进制数据,加载是类加载过程中的第一个阶段,在加载阶段,虚拟机需要完成以下三件事情: 类的加载指的是将类的.class文件中的二进制数据读取到内存中 将其放在运行时数据区的方法区内, 然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构 类加载的最终产品书位于堆区中的Class对象 Class对象封装了类在方法区内的数据结构,并像java程序员提供了访问方法去内的数据结构的接口。 Java程序对类的使用方式可以分为两种: -主动使用(六种) 1,创建类的实例 2,访问某个类或接口的静态变量,或者对该静态变量赋值 3,调用类的静态方法 4,反射(Class.forName(“com.jack.test”)) 5,初始化一个类的子类 6,Java虚拟机启动时被标明为启动类的类 -被动使用(除以上6种情况外,其他情况均为被动使用) 类加载器并不需要等到某个类被“首次主动使用”时再加载它,JVM规范允许类加载器在预料某个类将要被使用时就预先加载它,如果在预先加载的过程中遇到了.class文件缺失或存在错误,类加载器必须在程序首次主动使用该类时才报告错误(LinkageError错误),如果这个类一直没有被程序主动使用,那么类加载器就不会报告错误。 加载.class文件的方式: 从本地系统中直接加载 通过网络下载.class文件 从zip,jar等归档文件中加载.class文件 从专有数据库中提取.class文件 将Java源文件动态编译为.class文件 类加载器 不同的类加载器负责的组件不同,可分为2种类型 自定义类加载器(java.lang.classLoader的自来) java虚拟机自带类加载器 java虚拟机自带类加载器按类型又可分为三种类型: 启动类加载器:Bootstrap ClassLoader C/C++实现的负责加载存放在JDK\jre\lib(JDK代表JDK的安装目录,下同)下,或被-Xbootclasspath参数指定的路径中的,并且能被虚拟机识别的类库(如rt.jar,所有的java.开头的类均被Bootstrap ClassLoader加载)。启动类加载器是无法被Java程序直接引用的。 扩展类加载器:Extension ClassLoader 使用java代码实现该加载器由sun.misc.Launcher$ExtClassLoader实现,它负责加载JDK\jre\lib\ext目录中,或者由java.ext.dirs系统变量指定的路径中的所有类库(如javax.开头的类),开发者可以直接使用扩展类加载器。 应用程序类加载器:Application ClassLoader 使用java代码实现该类加载器由sun.misc.Launcher$AppClassLoader来实现,它负责加载用户类路径(ClassPath)所指定的类,开发者可以直接使用该类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。 双亲委派模型 双亲委派模型的工作流程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载,子加载器才会尝试自己去加载该类。 双亲委派机制: 当AppClassLoader加载一个class时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器ExtClassLoader去完成。 当ExtClassLoader加载一个class时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给BootStrapClassLoader去完成。 如果BootStrapClassLoader加载失败(例如在$JAVA_HOME/jre/lib里未查找到该class),会使用ExtClassLoader来尝试加载; 若ExtClassLoader也加载失败,则会使用AppClassLoader来加载,如果AppClassLoader也加载失败,则会报出异常ClassNotFoundException。 双亲委派模型意义: 系统类防止内存中出现多份同样的字节码 保证Java程序安全稳定运行 层次关系如下图: 验证 类被加载后,就进入连接阶段。连接就是将已经读取到内存的类的二进制数据合并到虚拟机的运行时环境中去 准备 在准备阶段,Java虚拟机为类的静态变量分配内存,并设置默认的初始值,这些内存都将在方法区中分配。 对于该阶段有以下几点需要注意: 这时候进行内存分配的仅包括类变量(static),而不包括实例变量,实例变量会在对象实例化时随着对象一块分配在Java堆中。 这里所设置的初始值通常情况下是数据类型默认的零值(如0、0L、null、false等),而不是被在Java代码中被显式地赋予的值。 例如对一下Sample类,在准备阶段,将为int类型的静态变量a分配4个字节的内存控件,并赋予默认值0,为long类型的静态变量b分配8个字节的内存控件,并赋予默认值0; public class Sample{ private static int a=1; private static int b; static{ b=2; } } 解析 在解析阶段,Java虚拟机会把类的二进制数据中的符号引用替换为直接引用。例如在Worker类的gotoWork()方法中会引用Car类的run()方法。 public void gotoWork(){ car.run(); //这段代码在Worker类的二进制数据中表示为符号引用 } 在Worker类的二进制数据中,包含了一个对Car类的run()方法的符号引用,它由run()方法的全名和相关描述符组成。在解析阶段,Java虚拟机会把这个符号引用替换为一个指针,该指针指向Car类的run()方法区内的内存位置,这个指针就是直接引用。 初始化 类初始化阶段是类加载过程的最后一步,到了初始化阶段,才真正开始执行类中定义的java程序代码。在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量赋予正确的初始值。在程序中,静态变量的初始化有两种途径: 在静态变量的声明处进行初始化 在静态代码库中进行初始化 在如下代码中,静态变量a和b都被显示初始化,而静态变量c没有被显示初始化,它将保持默认值0; public class Sample{ private static int a=1; private static int b; private static int c; static{ b=2; } } JVM初始化步骤: 假如这个类还没有被加载和连接,则程序先加载并连接该类 假如该类的直接父类还没有被初始化,则先初始化其直接父类 假如类中有初始化语句,则系统依次执行这些初始化语句 开开心心编码,快快乐乐生活。

优秀的个人博客,低调大师

【Python学习 】Python获取命令行参数的方法

背景 最近编写一个python程序的时候,需要去获取python命令行的参数,因此这里记录下如何获取命令行参数的方法。 一、sys 模块 在 Python 中,sys 模块是一个非常常用且十分重要的模块,通过模块中的 sys.argv 就可以访问到所有的命令行参数,它的返回值是包含所有命令行参数的列表(list), 参数个数: len(sys.argv) 脚本名: sys.argv[0] 参数1: sys.argv[1] 参数2: sys.argv[2] 下面我们通过程序来说明它的用法: #!/usr/bin/python # -*- coding: UTF-8 -*- import sys def main(): """ 通过sys模块来识别参数demo, http://blog.csdn.net/ouyang_peng/ """ print('参数个数为:', len(sys.argv), '个参数。') print('参数列表:', str(sys.argv)) print('脚本名为:', sys.argv[0]) for i in range(1, len(sys.argv)): print('参数 %s 为:%s' % (i, sys.argv[i])) if __name__ == "__main__": main() 下面我们通过命令行来运行该python脚本 1.1、不传递参数 我们执行命令 python test.py (venv) C:\Code Python\SMTP>python test.py 参数个数为: 1 个参数。 参数列表: ['test.py'] 脚本名为: test.py 识别到的参数只有一个,就是脚本名 test.py 1.2、传递多个参数 当我们传递参数的时候, 我们执行命令 python test.py ouyangpeng csdn (venv) C:\Code Python\SMTP>python test.py ouyangpeng csdn 参数个数为: 3 个参数。 参数列表: ['test.py', 'ouyangpeng', 'csdn'] 脚本名为: test.py 参数 1 为:ouyangpeng 参数 2 为:csdn (venv) C:\Code Python\SMTP> 识别到的参数有3个,分别是脚本名 test.py,参数 1 为:ouyangpeng,参数 2 为:csdn 1.3、传递多个参数和命令行选项 当我们传递命令行选项和参数的时候, 我们执行命令 python test.py ouyangpeng csdn -u username -p password (venv) C:\Code Python\SMTP>python test.py ouyangpeng csdn -u username -p password 参数个数为: 7 个参数。 参数列表: ['test.py', 'ouyangpeng', 'csdn', '-u', 'username', '-p', 'password'] 脚本名为: test.py 参数 1 为:ouyangpeng 参数 2 为:csdn 参数 3 为:-u 参数 4 为:username 参数 5 为:-p 参数 6 为:password 识别到的参数有6个,分别是脚本名 test.py,参数 1 为:ouyangpeng,参数 2 为:csdn,命令行选项 -u 和 -p 都被识别为参数了,这样不合理,因此我们需要引入getopt模块来识别命令行选项。 二、getopt模块 getopt模块是专门处理命令行参数的模块,用于获取命令行选项和参数,也就是sys.argv。命令行选项使得程序的参数更加灵活。支持短选项模式(-)和长选项模式(–)。 该模块提供了两个方法及一个异常处理来解析命令行参数。 2.1 getopt.getopt 方法 getopt.getopt 方法用于解析命令行参数列表,语法格式如下: getopt.getopt(args, options[, long_options]) 方法参数说明: args: 要解析的命令行参数列表。 options: 以字符串的格式定义,options后的冒号(:)表示该选项必须有附加的参数,不带冒号表示该选项不附加参数。 long_options: 以列表的格式定义,long_options 后的等号(=)表示如果设置该选项,必须有附加的参数,否则就不附加参数。 该方法返回值由两个元素组成: 第一个是 (option, value) 元组的列表。 第二个是参数列表,包含那些没有’-‘或’–’的参数。 2.1 Exception getopt.GetoptError 在没有找到参数列表,或选项的需要的参数为空时会触发该异常。 异常的参数是一个字符串,表示错误的原因。属性 msg 和 opt 为相关选项的错误信息。 2.3 实例 了解了 sys 模块和 getopt 模块,我们就可以来自己编写一个带有命令行的程序并且在该程序中,我们还使用了 getopt.GetoptError 来进行异常处理。代码如下: #!/usr/bin/python # -*- coding: UTF-8 -*- import sys import getopt def main(argv): """ 通过 getopt模块 来识别参数demo, http://blog.csdn.net/ouyang_peng/ """ username = "" password = "" try: """ options, args = getopt.getopt(args, shortopts, longopts=[]) 参数args:一般是sys.argv[1:]。过滤掉sys.argv[0],它是执行脚本的名字,不算做命令行参数。 参数shortopts:短格式分析串。例如:"hp:i:",h后面没有冒号,表示后面不带参数;p和i后面带有冒号,表示后面带参数。 参数longopts:长格式分析串列表。例如:["help", "ip=", "port="],help后面没有等号,表示后面不带参数;ip和port后面带冒号,表示后面带参数。 返回值options是以元组为元素的列表,每个元组的形式为:(选项串, 附加参数),如:('-i', '192.168.0.1') 返回值args是个列表,其中的元素是那些不含'-'或'--'的参数。 """ opts, args = getopt.getopt(argv, "hu:p:", ["help", "username=", "password="]) except getopt.GetoptError: print('Error: test_arg.py -u <username> -p <password>') print(' or: test_arg.py --username=<username> --password=<password>') sys.exit(2) # 处理 返回值options是以元组为元素的列表。 for opt, arg in opts: if opt in ("-h", "--help"): print('test_arg.py -u <username> -p <password>') print('or: test_arg.py --username=<username> --password=<password>') sys.exit() elif opt in ("-u", "--username"): username = arg elif opt in ("-p", "--password"): password = arg print('username为:', username) print('password为:', password) # 打印 返回值args列表,即其中的元素是那些不含'-'或'--'的参数。 for i in range(0, len(args)): print('参数 %s 为:%s' % (i + 1, args[i])) if __name__ == "__main__": # sys.argv[1:]为要处理的参数列表,sys.argv[0]为脚本名,所以用sys.argv[1:]过滤掉脚本名。 main(sys.argv[1:]) 2.4 运行结果 2.4.1、不传递参数 当我们不传递参数的时候, 我们执行命令 python test_arg.py (venv) C:\Code Python\SMTP>python test_arg.py username为: password为: (venv) C:\Code Python\SMTP> 2.4.2、使用短格式选项,不传递参数 当我们使用短格式选项,不传递参数的时候, 我们执行命令 python test_arg.py -h (venv) C:\Code Python\SMTP>python test_arg.py -h test_arg.py -u <username> -p <password> or: test_arg.py --username=<username> --password=<password> 2.4.3、使用长格式选项,不传递参数 当我们使用长格式选项,不传递参数的时候, 我们执行命令 python test_arg.py --help (venv) C:\Code Python\SMTP>python test_arg.py --help test_arg.py -u <username> -p <password> or: test_arg.py --username=<username> --password=<password> (venv) C:\Code Python\SMTP> 2.4.4、使用短格式选项,传递参数 当我们使用短格式选项,传递参数的时候, 我们执行命令 python test_arg.py -u ouyangpeng -p csdn (venv) C:\Code Python\SMTP>python test_arg.py -u ouyangpeng -p csdn username为: ouyangpeng password为: csdn (venv) C:\Code Python\SMTP> 2.4.5、使用长格式选项,传递参数 当我们使用长格式选项,传递参数的时候, 我们执行命令 python test_arg.py --username=ouyangpeng --password=csdn (venv) C:\Code Python\SMTP>python test_arg.py --username=ouyangpeng --password=csdn username为: ouyangpeng password为: csdn (venv) C:\Code Python\SMTP> 2.4.6、使用长短混合格式选项,传递参数 当我们使用长短混合格式选项,传递参数的时候, 我们执行命令 python test_arg.py -u ouyangpeng --password=csdn (venv) C:\Code Python\SMTP>python test_arg.py -u ouyangpeng --password=csdn username为: ouyangpeng password为: csdn (venv) C:\Code Python\SMTP> 2.4.7、使用格式选项,传递部分参数 当我们使用长短混合格式选项,传递参数的时候, 我们执行命令 python test_arg.py -u ouyangpeng (venv) C:\Code Python\SMTP>python test_arg.py -u ouyangpeng username为: ouyangpeng password为: (venv) C:\Code Python\SMTP> 2.4.8、传递错误的选项参数 当我们使用错误的格式选项传递参数的时候, 我们执行命令 python test_arg.py -e,-e选项不正确 (venv) C:\Code Python\SMTP>python test_arg.py -e Error: test_arg.py -u <username> -p <password> or: test_arg.py --username=<username> --password=<password> (venv) C:\Code Python\SMTP> 2.4.9、传递选项参数以及不带选项的参数 当我们传递选项参数以及不带选项的参数的时候, 我们执行命令 python test_arg.py -u ouyangpeng --password=csdn arg1 arg2 arg3 arg4 (venv) C:\Code Python\SMTP>python test_arg.py -u ouyangpeng --password=csdn arg1 arg2 arg3 arg4 username为: ouyangpeng password为: csdn 参数 1 为:arg1 参数 2 为:arg2 参数 3 为:arg3 参数 4 为:arg4 (venv) C:\Code Python\SMTP> 作者:欧阳鹏 欢迎转载,与人分享是进步的源泉! 转载请保留原文地址:http://blog.csdn.net/ouyang_peng/article/details/79390920 如果觉得本文对您有所帮助,欢迎您扫码下图所示的支付宝和微信支付二维码对本文进行随意打赏。您的支持将鼓励我继续创作!

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册