Perl6的开发如何做到自动化?其实很简单,只需要一个应用Tomtit。
Tomtit是一个全新的Perl6任务运行器,可让你很便捷地自动执行日常任务。
本文中,我们将展示如何使用Tomtit实现Perl6开发自动化,我们以实例展示Perl6开发中的典型场景:设置git存储库、测试本地源代码、安装本地源代码、发布CPAN模块。关于Tomtit的详细介绍请参考文章(https://dev.to/melezhik/one-tomtit-for-it–1j3f)。
本文译自Alexey Melezhik 的博客,原文链接 https://dev.to/melezhik/automation-of-perl6-development-workflow-through-the-tomtit-task-runner-10jj
Tomit的安装很简单只需通过Perl6 模块生态系统命令zef:
zef install Tomtit
现在让我们从远程git存储库获得本实例应用程序源代码:
git clone $ git-repo
本文的内容限制为在Perl6开发和发布时典型的应用场景:设置git存储库、测试本地源代码、安装本地源代码、发布CPAN模块。
首先我们为每个涉及的实例定义tomtit场景。场景配置文件位于.tom目录中,配置文件为纯Perl6脚本,同这些脚本调用Tomtit API。
在新建应用时候,先要设置用户和电子邮件,这样可以支持push到远程git仓。我们也希望在缓存中保存git密码。防止每次手动输入,这些任务都可以在.tom文件中配置:
.tom/set-get.pl6:
task-run “set git”, “git-base”, %(
email => ‘[email protected]’,
name => ‘chongchong’,
config_scope => ‘local’,
set_credential_cache => ‘on’
);
实例中的工作流程有点复杂,需要将源代码推送到GitHub和BitBucket两个远程库。
为push操作的任务场景配置也很容易:
.tom/push-gh.pl6:
# push到 github
bash “git push origin master”;
.tom/push-bb.pl6:
# push 到bitbucket
bash “git push bb master”;
.tom/push.pl6:
# push到github和bitbucket
EVALFILE “.tom/push-bb.pl6”
EVALFILE “.tom/push-gh.pl6”
对于许多Perl6项目,会通过zef test
测试
在t/目录中的单元测试用例,本例子中我们还要做Outthentic测试并且验证META6.json文件,看看是否有任何JSON语法错误,任务的配置实例如下:
.tom/test.pl6:
task-run “check json files”, “json-lint”, %( path => “{$*CWD}” );
bash “zef test .”;
bash “sh run-test.sh”;
该操作简单,只是在当前工作目录的下执行zef install命令。
.tom/install.pl6:
bash “zef install . –force-install”;
实例中我们使用App::Mi6工具将Perl6模块打包并发布到CPAN,执行该操作首先要在它需要通过~/.pause配置CPAN Update的用户和密码,下面是该任务的配置文件:
.tom/set-pause.pl6:
my $password = prompt(“enter your CPAN password: “);
template-create “/home/{%*ENV<USER>}/.pause”, %(
mode => ‘700’,
variables => %(
user => ‘chongchong’,
password => $password
),
source => q:to /TEMPL/
user [%= user %]
password [%= password %]
TEMPL
);
发布的任务配置就简单了:
.tom/release.pl6:
zef “App::Mi6”;
bash “mi6 release”;
当tomtit场景准备就绪时,开发工作流就变的简单明了,当一切都配置到位的时候:
1、chekout应用程序源代码:
git clone $git-repo
2、安装Tomtit:
zef intall Tomtit
3、列出可用的tomtits任务:
tom –list
4、修改源代码
vim foo/bar/app.pl6
5、运行测试:
tom test
安装应用:
tom install
6、设置git repo:
tom git-setup
7、提交更改
git commit -a
8、推送更改:
tom push
9、设置PAUSE帐户凭据:
tom set-pause
10、发布到CPAN:
tom release
本文中,我们实现了Perl6开发的自动化任务执行过程,所有操作只需要Tomtit就可以实现。更多典型任务请关注官方文档和探索。
]]>Tomtit是基于Perl6语言开发的任务执行器,它方便好用、任务定义快捷简洁,内置数十个常用场景任务插件,利用该雀儿帮我们自动化Perl/Perl6以及更多的语言开发任务。
最适合Perl5/Perl6开发人员,也支持其他开发场景使用;
支持Perl6语言的编程API;
自带许多常见任务任务配置:运行Bash脚本、创建文件和启动/停止服务 ,更多的任务脚本详见:
https://github.com/melezhik/sparrowdo/blob/master/core-dsl.md
它有几十个插件,详细列表请访问http://sparrowhub.org
支持扩展, 你可以使用自己喜欢的语言并编写新的插件来满足的特定需求。
最重要的是作为底线,它可以帮助我们轻松完成常见的任务,但不限于静态DSL,而是允许你使用现代化的强大的Perl6语言来配置任务场景。说这么多,你一定心动了把,那让咱们开始把。
Tomtit是一个标准的Perl6模块,可以使用Perl6模块生态系统包管理软件zef安装。
zef install Tomtit
成功安装后,Tomcatit在你的shell环境增加tom -命令行客户端来执行具体的任务。
你需要一个系统引启动器(*)来引导Tomtit的内部任务器的运行,实际上就是一个简单的命令
tom –bootstrap
注意:你需要sudo权限来启动该任务器。
完成启动后,你就可以执行任务脚本,接着让我们来看看典型的tomtit工作流程。
通常使用tomtit的工作流程是先定义方案(任务脚本),然后运行它们时。它基于任务为中心的方法非常便捷,我们可以检查应用程序的源代码并运行一些相关的任务。比如,我们有一个应用程序源代码,我们只需执行3个标准操作:
build,测试和安装
我们定以后任务方案后,我们命名他们然后构建,测试和安装。如果使用make程序来构建项目,则方案对应make对应参数的3次调用。让我们创建我们的第一个Tomtit场景:
git checkout $git-repo
mkdir .tom
nano .tom/build.pl6
nano .tom/test.pl6
nano .tom/install.pl6
每个场景的代码和bash命令运行make一样简单:
.tom/build.pl6:
bash “make”
.tom/test.pl6:
bash “make test”
.tom/install.pl6:
bash “sudo make install”
tomtit的任务方案场景的脚本是用Perl6编写的,对应于调用不同的任务,但这些场景不一定是有限的任务调用,它们只是Perl6程序,基于Perl6的强大功能你可以使用它做任何事情。
Tomtit中有两种语法不同的任务。你通过任务运行函数调用的第一个是快捷方式,它与task-run几乎相同但具有助记符名称,有时更容易签名。
在上述make实用程序的场景中,我们使用bash快捷方式调用一段Bash代码。tomtie可调用的完整快捷方式列表,请浏览:
https://github.com/melezhik/sparrowdo/blob/master/core-dsl.md
换句话说,任务运行和快捷方式只是一种调用任务块的方法,如果代码从SparrowHub下载,脚本存储库然后由sparrow内部脚本运行执行,虽然不之前没有提到过,但实际上zoo-repository支持更多的birds!
这些小脚本或任务也叫Sparrow插件。Tomtits的任务场景基对应于一个执行的Sparrow插件或任务的列表。
通过运行tom –list,你可以到当前可用的所有任务场景:
[scenarios list]
build
test
install
一旦定义了任务方案,就可以通过tom –run=$scenario命令运行它们。例如:
tom run = build,tom run = test等等。
要回想一下你运行的最后一个场景是什么,可使用tom –last命令。更多文档,请参考tomtitgithub页面的tom命令行的相关说明。
就上上文中我们提到的,我们不必受限于Tomtit场景中运行Bash和官方一些标准的任务场景。我们可以下载和自己开发相关插件,可以实现各种形形色色的任务。
例如,我们创建一个用用户参数(如用户名和电子邮件)配置本地git存储库的方案。你要clone一个新项目时,通常需要对其做修改并提交修改,最后push到远程库。那么本任务就是帮助你实现这个任务,并能自动缓存用户账号信息,以后不需要再输入用户名和密码(http/https)。
.tom/git-setup.pl6:
task-run “set git”, “git-base”, %(
email => ‘[email protected]’,
name => ‘chongchong’,
config_scope => ‘local’,
set_credential_cache => ‘on’
);
通过设置config_scope,我们定义任务为对本地git存储库进行设置,并通过设置set_credential_cache为“on”,我们要求git缓存密码。
可以在SparrowHub的sparrow插件存储库中找到可在Tomtit方案中使用的插件列表。
在下面的场景示例中,我们创建任务以通过vsts-build插件远程运行VSTS构建:
.tom/build-vsts.pl6:
task_run “run my build”, “vsts-build”, %(
definition => “BackEndBuild”
)
你可以在Tomtit方案中使用许多其他插件作为任务。 关于更多的插件,请查看SparrowHub存储库SparrowHub。
Tomtit为我们提供了大量可用于日常任务的小脚本或插件,尤其是在处理开发类的源代码管理和自动化构建的任务。Tomtit任务场景配置脚本使用的是普通Perl6脚本,用于生成执行任务的动态列表。任务脚本支持语法糖,你可以使用预定义的内置函数集,而不是引用插件,使代码更简洁,更容易阅读。
如果由于某些原因你找不到解决你特定任务的插件,你可以随时创建自己的插件。
]]>
目前 Perl 6 版本发布周期是季度性发布。
需要提及的是,本次发布的 Rakudo Star 版本不能完全向后兼容 JVM 所有功能,只能完全向后兼容 MoarVM。
本地发行包 —— 包括 2018.01 版本的 Rakudo Perl 6 编译器,MoarVM 虚拟机及核心模块、文档以及 Perl 6 社区收集的其他资源。
Rakudo 编译器的更新列表,详见安装包 rakudo/docs/announce 目录下的 2017.10、2017.11.md、2017.12.md、2018.01.md 文档里。
额外科普:
Perl 6 仅仅指语言,Rakudo Star 是官方的 Perl 发行版本,包括编译器、虚拟机和核心功能模块。当然 Perl 6 还有其他官方和第三方的 Perl 6 发行版版本,比如大家都熟悉的春哥的 fanlang 语言就是运行在 Openresty 上的Perl 6 “方言“。
MoarVM 是官方的 Perl 6 虚拟机,Perl 的虚拟机还支持 Java 虚拟机的 JVM,用于在 JVM 上跑 Perl 6。
Perl 6 文档中文化 —— 笔者在 github 上创建了一个官方文档 Perl 6 doc 中文化项目,欢迎有志的同学一起加入,完善和推广。
码云的托管地址为:https://gitee.com/ijz/perl6doc
perl -ne 'print if 5..10' xxoo #感谢flw提醒,忘记这个了
perl -ne 'print if $.>=5 and $.<=10' xxoo
perl -ne 'print if int($.) ~~ (5..10)'
perl -ne 'print if grep { $_ == $. } 5..10'xxoo
sed -ne '5,10 p' xxoo
awk 'NR==5,NR==10' xxoo
head -10 xxoo |tail -6
tail -n +5 xxoo | head -n 6
grep . -n xxoo |grep -E "^(5|6|7|8|9|10):"|perl -lpe 's/\d+://'
17年磨一剑,在perl人艰苦卓绝的努力下,perl 6终于在2015年圣诞节推出了正式版本V6.c版本(c代表圣诞节)。 期间几度波折,发生了很多很的事情。最令人津津乐道的一条是Perl6 最先成型的pogs版本主程台湾大牛唐宗汉易性为唐凤,另IT界叹为观止,广泛流传。
20年积累了宇宙巨能的perl6究竟有啥黑科技?本文借自perl6官方的faq,翻译成中文,以帮助我们揭开perl6的潘多拉宝盒。
笔者计划一项目perl6doc中文化的项目,这篇文章为perl6doc中文化的第一个成果,如果有什么纰漏和错误,请帮助我指出 。另外有志于学习perl6和参与项目的同仁也大大的欢迎哦。
项目的地址为:http://git.oschina.net/ijz/perl6doc
最新更新是Perl6.d版本将会在2018年推出,让我们期待把!
正确的说法是, Rakudo 是perl6的的实现。它是目前最完全的实现版本,目前还存在其他几个实现,将来也许 会有更多的实现。Perl 6是语言的定义。目前来讲,Perl 6和Rakudo名称可以通用。
NO,perl 6 第一个正式发布版是v6.c(c代笔Christmas圣诞节)。 接下来发布的版本是带点版本(比如,v6.3.2),或者大版本的话(v6.d)
运行perl6 -v
会输出编译器版本号:
$ perl6 –v
输出”This is Rakudo version 2017.07 built on MoarVM version 2017.07 implementing Perl 6.c“。
2018年内某时间点。这是实现6.d特性的第一个版本,具体日期后面会发布。 实际上通过使用use v6.d.PREVIEW
我们已经在6.c的编译支持了很多6.d的新特性 pragma。
Mac用可安装Rakudo Star DMG包,下载地址: http://rakudo.org/downloads/star
Windows用户可以通过Rakudo Star MSI安装. 你必须事先安装Windows Git和Strawberry Perl5 然后用zef包管理软件安装perl6模块。
Linux用户直接下载Rakudo Star http://www.perl6.org/downloads/ ,然后编译安装.
Linux和Mac用户也可以通过操作系统发行方或者第三方的二进制包安装,发行方包可能版本会老一点.
我们也提供Rakudo Star docker容器的镜像,地址为 https://hub.docker.com/_/rakudo-star/
X<|rakudobrew (FAQ)>
最简便的方法是clone仓库the repository并且对其编译 从源码编译文档。
部分人也可以选择rakudobrew这允许我们安装多版本 rakudo,从中选择自己喜欢的版本。请先浏览文档 rakudobrew 这个工具相当于perl5的perlbrew或者python,ruby的相应的多版本管理工具。
请浏览官方文档站(特别是他的“Language”部分。 还有资源页)。 你可以通过在线perl6频道寻求帮助 或者通过谷歌搜索聊天记录。
Perl6 specification是指perl6 官方的测试套件.我们称它为roast,其地址为 hosted on github. 任何编译测试通过的就会加入到Perl 6 specification。
Roast的主分支对应最新的开发版本,它仍未划入任何的specification。其他分支则对应于不同的specific版本。 例如,”6c.errata”。
是的, 其链接为glossary.
本文档的Language部分,有几个5to6-
的指导教程。 其中最主要的是5to6-nutshell guide。
请浏览’rb-nutshell’文档,链接为https://docs.perl6.org/language/rb-nutshell
有,和Per5的CPAN一样,CPAN已经完全支持Perl6。唯一的区别是用PAUSE 升级模块时候,你必须选择Perl 6
为目标目录。App::Mi6
工具 模块可用于,简化这个更新流程。最新版本的zef
模块安装 自动的检查CPAN上最新版本的模块,以及GitHub-based ecosystem。
没问题,通过 Inline::Perl5可以很好的运行大多数的perl5模块,甚至 包括Catalyst和DBI.
Nativecall使这工作变的非常简单.
这是Debian系linux运行Nativecall常见的问题.你需要安装C包,并对缺失的问题设置符号链接。
利用Nativecall调用它们非常简单。同时还有一个生态系统模块POSIX也可用.
Rakudo Star发行包携带很多有用的了 模块。 Rakudo编译器发布仅仅包括一些最常用的基本模块。 更多的模块在ecosystem。
使用--target=optimize
命令行选项来预览程序中的AST。例如: perl6 --target=optimize -e 'say "hi"'
。 静态优化后,optimize
赋给AST处理目标,同时目标 ast
给予AST前面的步骤。 可通过运行perl6 --stagestats -e ""
得到所有可用目标的列表。
典型地是使用say
例程,对”gist” 对象的dump使用gist
方法。更多细节可以通过 perl
方法,这通常会返回 EVAL
样式的代码表示。
如果使用是rakudo implementation,你可以使用其特有的 non-standard dd
routine例程来dump 他的输出与perl
类似,包含更多多的信息。例如:
my $foo = { foo => ‘bar’ };
say $foo.perl;# 输出: «${:foo(“bar”)}»
say $foo;# 输出: «{foo => bar}»
# 在rakudo实现中,支持非标准的例程
dd $foo;# 输出: «Hash $foo = ${:foo(“bar”)}»
同时perl6生态系统也有几个专门的模块提供更完善 的数据结构dump,包括支持带彩色的输出等。
请安装Linenoise 模块.
对Unix系的操作系统另外还有一个方法就是使用rlwrap。在debian系操作系统可以通过 运行以下命令安装。
for code :lang<shell>
sudo apt–get install rlwrap
如果 当前输出是编译时错误,否则是运行时错误。
例如:
=begin code :skip–testsay 1/0;# 试图对0整除sub foo( Int $a, Int $b ) {…}foo(1)# ===抱歉!=== 编译时报错 …=end code
1234567 | =begin code :skip–testsay 1/0;# 试图对0整除sub foo( Int $a, Int $b ) {…}foo(1)# ===抱歉!=== 编译时报错 …=end code |
(Any)
是啥?Any是最高层的基类,其它绝大多数类都继承它。Any
类型对象最为变量和参数 未明确指类型时候的默认值 这意味着当你答应一个没有任何值gist
变量时候会输出(Any)
。比如使用say
routine:
1234567891011 | =begin codemy $foo;say $foo; # 输出: «(Any)»my Int $baz;say $baz; # 输出: «(Int)»my $bar = 70;say $bar; # 输出: «70»=end code |
为了测试一个变量是否具有定义的值,使用L和L例程。其他几个测试定义与否结构有: with
, orwith
,以及without
语句, [<//>
(/routine/$SOLIDUS$SOLIDUS),andthen
, notandthen
,以及orelse
操作符。还有 type constraint smileys。
so
是什么?so
是一个弱优先级操作符,强制为Bool。 它和?
前缀操作符具有相同语义,类似于and
和低优先级的&&
。
实例:
12 | say so 1|2 == 2;# 输出: «True» |
本例中的,比较的结果(是一个 Junction),被转化为布尔型打印。
:D
和 :U
修饰的意义?在perl6中,类和其他类型都是对象,并且只能通过其自己类型的类型检查。
例如,如果你定义一个变量
12 | my Int $x = 42; |
然后你不仅可以给他赋值整数(那就是,类实例Int),还有Int
类型对象自己。
如果你要排除类型对象,你可以附加:D
类型笑脸,他带包已”定义”.
1234567 | =begin code :skip–testmy Int:D $x = 42;$x = Int;# 异常退出:# 给$x赋值是类型检查错误;# 期待 Int:D 但是赋值的是Int=end code |
类似的,C<:U> 限制为未定义的值,也就是说,类型对象。如果你限制既不能为类型对象 也不能为实例,你可以用C<:_>.
-->
有啥作用?L«–>|/type/Signature#Constraining_Return_Types» 为限制返回为一个类型或者一个定义的值.
例子,限制为一个类型:
123456789 | =begin code :skip–testsub divide–to–int( Int $a, Int $b —> Int ) {return ($a / $b).narrow;}divide–to–int(3, 2)# 返回值类型检查失败期待Int但是返回Rat=end code |
例子,限制为一个定义的返回值:
1234 | sub discard–random–number( —> 42 ) { rand }say discard–random–number;# 输出: «42» |
在本例中,由于返回值已经定义,所以最终值被抛弃。
如果你想从Junction中,抽取值,你可能做错了,你需要的应该是 Set。
Junctions表示匹配的意思,不用来做操作的。如果你费用坚持这样做,你可以滥用自动线程:
123456789 | sub eigenstates(Mu $j) {my @states;–> Any $s { @states.push: $s }.($j);@states;}say eigenstates(1|2|3).join(‘, ‘);# 打印出 1, 2, 3 或者一个置换方法。 |
s///
如何工作? $i++
如何工作?perl6中,许多基本类型的值都是不可改变的,但是存放他们的变量却不是,C<s///> 操作符是对 变量的操作,操作是会生成一个新的字符串对象。同样,C<$i++>也是工作C<$i>变量上,并不是对 值本身的操作。
知道这点后,我们一般就不会试图去修改一个字符串(比如'hello' ~~ s/h/H/
) 但是可能不经意间使用 map
做了这样事情:
12345678 | my @foo = <hello world>.map: { s/h/H/ } ; # 抛出异常,# “Cannot modify an immutable Str (hello)”my @bar = <hello world>».subst–mutate: ‘h’, ‘H’; # 抛出异常,# “Cannot resolve caller subst-mutate(Str: Str, Str);# the following candidates match the type but require# mutable arguments: …” |
实际上,要做的不是修改原始值,而是返回一个新的值得操作
123 | my @foo = <hello world>.map: { S/h/H/ };# [‘Hello’,’world’]my @bar = <hello world>».subst: ‘h’, ‘H’; # [‘Hello’,’world’] |
更多信息,可以浏览 containers。
@
前缀么?在perl6中,一切皆引用,所以专门谈论引用意义不大。不像perl5,标量变量也能直接包含数组:
12345678 | my @a = 1, 2, 3;say @a;# 输出: «[1 2 3]»say @a.^name;# 输出: «(Array)»my $scalar = @a;say $scalar;# 输出: «[1 2 3]»say $scalar.^name;# 输出: «(Array)» |
最大的不同是插入标量中的数组当为列表上下文的一个值,而数组则会循环迭代。
1234567891011121314 | =begin code :skip–testmy @a = 1, 2, 3;my $s = @a;for @a { … }# 循环3次for $s { … }# 只会循环一次my @flat = flat @a, @a;say @flat.elems;# 输出: «6»my @nested = flat $s, $s;say @nested.elems;# 输出: «2»=end code |
你可以用@( ... )
或者 用表达式的.list
方法,强制展开,或者为成员上下文(不能展开)
有几个原因:
你可能是想混用字符解释器和HTML
12345 | =begin code :skip–testmy $foo = “abc”;say “$foo<html-tag>”;=end code |
perl6认为$foo
为一个哈希,而C«<html-tag>»会被当成字符哈希键。我们用一个 大括号来加深理解:
123 | my $foo = “abc”;say “{$foo}<html-tag>”; |
yield
呢?perl6没有像python一样的yield
语句,但是它通过懒列表提供类似地函数式功能。 有两种普遍的方法写协程,返回懒列表
12345678910111213 | =begin code :skip–test# 第一种方法, gather/takemy @values = gather while have_data() {# do some computationstake some_data();# do more computations}# 第二种方法, 对一个懒列表使用.map或者类似的方法my @squares = (1..*).map(–> \x { x² });=end code |
诸如下面代码:
12345678 | class A {has $!x;method show–x {say $!x;}}A.new(x => 5).show–x; |
输出不为5。私有属性是_private_,这意味着对外不可见。如果默认构造函数可以初始化他们的话, 他们就可能暴露在公共API.
如果你坚持要这样做,可以增加一个submethod BUILD
来初始化他们:
123456789 | class B {has $!x;submethod BUILD(:$!x) { }method show–x {say $!x;}}B.new(x => 5).show–x; |
BUILD
会被默认的构造函数调用(间接地,查看 Object Construction了解更多),构造函数调用 所有用户传递过来的命名的参数。:$!x
是命名为x
的命名参数,当带 x
命名参数被调用 时,他的值会被绑定到属性 $!x
。
如果不这样做。如果名称是公有的,这样定义$.x
也是没有害处。因为默认外部视图是只读的, 你仍然只能通过内部地 $!x
操作它。
say
, put
和 print
有啥区别?最明显地差异是 say
和 put
输出会自带换行符,但是print
没有。
其他的不同时:print
和put
通过调用Str
方法把所有参数项会当成一个字符串,say
则 是用 gist
方法。前者适合机器,后者更人性化。
或者完全的不同,$obj.Str
给出一个字符表达,$obj.gist
给出一个简单对象总结,适合开发人员 辨别。 $obj.perl
会给出一个perl式的表达。
例如:类型对象,也叫做“未定义值”,字符化结果为一个空串,并且给予警告。而gist
方法会返回 类型的名称,紧跟着一个空括弧(表示除了类型外没有任何值)。
my Date $x;# $x包含一个Date类型对象
print $x;# 输出为空和警告
say $x;# 输出: «(Date)»
所以,say
更适合做调试;显示是人优化过的; print
和put
更适合给其他应用输出结果。
put
是介于print
和say
之间的调和。和print
一样适合为其他程序输出结果,同时也像 say
一样输出结果自带换行。 and like say
, it adds a newline at the end of the output.
token
和rule
有何不同 ?<regex>,token
和rule
都用于引入正则表达式,但是语法上略有不同。
token
意味着:ratchet
或者:r
修饰符,这会防止规则被回溯。
rule
表示:ratchet
和:sigspace
(简写为:s
)修饰符,意味着规则不可以回溯,并且将 正则表达式中空白符号作为 C«<.ws>» 调用(不捕获)(例如,可以用来匹配空格,除了两单词之间的空格)。 正则表达式开头和每个可选分支|的开头空白会被忽略。
regex
定义一个没有任何暗示修饰符的纯正则.
die
和fail
有啥不同?die
抛出一个异常.
fail
返回一个Failure
对象.(如果在词法范围内调用定义过 use fatal;
),fail
抛出一个异常 而不是返回)。
Failure
是一个非抛出或者“懒”异常。它一个包含了异常的对象,如果你想用 Failure
作为普通对象 抛出一个异常。或者在sink上下文中忽略它。
Failure
在defined
检查中返回False
,你可以用 exception
方法抽取异常。
wantarray
和want
不见了? 我怎么才能不同上下文中返回不同的类型?perl5用wantarray
函数来测试调用的对象是void, scalar或者列表。perl6没有这样的结构,因为在perl6中上下文不再是关键;例如, 一个例程不需要知道哪个上下文被调用了,因为上下文是惰性的(只有在最后结果被使用时候才会知道)。
例如,perl6有多调度器,所以,下面的代码:
=begin code :skip–test
multi w(Int $x) { say ‘Int’ }
multi w(Str $x) { say ‘Str’ }
w(f());
=end code
没有办法知道调用的 sub f
需要一个字符串或者整数,由于它自己现在也不知道会调用啥 一般来讲,这需要解决halting问题,对perl编译器作者也是个头疼的问题。
实现perl6上下文敏感的一个方法是返回一个对象。它知道如何响应上下文中典型的方法调用。 在perl6中,相比较它听起来,这实际上是一个lot easier, 和其他语言的其他特性,既可以减轻首先需要的并且最大可能是覆盖到wantarray的用例。
例如,regex匹配返回匹配对象,知道如何影响列表索引,哈希索引。并且可以变成匹配字符串
Pointer
和OpaquePointer
有什么不同?OpaquePointer
已经过时,被Pointer
取代了.
目前,开发最完善是Rakudo(支持多虚拟机后端)。曾经的实现包括Niecza (.NET)和 Pugs (Haskell)。 其他客用的实现请浏览Perl 6 Compilers
我们可以最直接告诉你Rakudo基本上都是用perl6开发的。说的细一点的话,Rakudo使用perl和 NQP (“Not Quite Perl”)混合开发的。NQP是一个轻量地类perl6虚拟机环境。它设计用perl6语法来实现高级别 虚拟机(比如MoarVM and JVM)编译器和类库。
NQP是以下各部分构成 (1) NQP代码, (2) 底层虚拟机使用的各种语言 (3) 一些第三方的 C和库, 以及(4)一些早期编译进程的运行时启动文件
不是说是,也不能说完全不是 (not (not Nil))
关于这个问题教主Larry这样回答的: Rule 1
… As opposed to some other name that did not imply all the things that the higher number might indicate on other languages.
… 相比较换个不能说明任何事情的名字,一个高的版本号也可能暗示是一个完全不同语言。
perl社区认为Perl5和Perl6是姊妹语言,他们有很多共同点,解决了许多相同的问题, 但是Perl6并不为了取代Perl 5。事实上,两种语言互相影。
尽管编程语言和他们的编译不是一个是与非得二元问题。因为还牵扯到语言本身和实现的 问题,他们会变越来越好用。根据个人需求的不同,perl6及编译器可能是可用或者不可用。 (截止目前,目前99.9的功能都实现了,只是还稍微有点慢 __译者)。
6.c版本(2015圣诞节)是Perl 6首次正式发布版本,发布包括一个验证套件和的编译器。
perl6实现了通常其他程序中没有的许多伟大的想法。虽然有几种语言提供了这些特性中的部分, 但没有一种语言能支持所有这些:
那要取决于你要拿它做什么。Rakudo开发的秉承“工作的更合适,而不更快”的宗旨。一些部分 已经足够快,还有一些还需要改善。
相比较其他动态语言perl6提供了很多JIT特性,还有很大性能提升空间。在一些问题上已经比perl5快了。
perl5程序员应该了解perl了内置了更多的函数,简单的基准性能测试并不能说明什么问题,除非你perl5 测试用例包括了诸如Moose,类型检测模块等复杂的项目。
下面提供了写粗略的基准脚本,表明如果使用了复杂的模块的任务上Perl6比Perl5要快,与此同时,如果 不涉及这些重模块Perl5则会更快。
在你的系统运行下面脚本,结果可能会让你大吃一惊。
例子:
=begin code :skip–test
# Perl6 版本
use v6.c;
class Foo { has $.i is rw };
for 1..1_000_000 –> $i {
my $obj = Foo.new;
$obj.i = $i;
}
# Perl5 版本
package Foo;
use Moose;
has i => (is => ‘rw’);
__PACKAGE__–>meta–>make_immutable;
for my $i (1..1_000_000) {
my $obj = Foo–>new;
$obj–>i($i);
}
1;
# 另一个Perl5版本,相比较Moose/Perl6版本,提供少量仅仅需要特性,更简单程序。
package Foo;
use Mojo::Base –base;
has ‘i’;
for my $i (1..1_000_000) {
my $obj = Foo–>new;
$obj–>i($i);
}
1;
# 一个脚本运行在perl5 (with perl -Mbigint)和perl6下
my ($prev, $current) = (1, 0);
for (0..100_000) {
($prev, $current) = ($current, $prev + $current);
}
print $current;
=end code
</code><code>
]]>这儿介绍第三种方法(如果网站固定文件不变的情况下)
网站部署好后,通过对站点所有文件的计算MD5值,并保存在一个文件中。然后以后可以手动或者crontab,监控程序等定期对保存文件中的文件生成md5值和已有的md5值对比,如果发现值对不上,则说明文件被篡改了。
程序perl:
#!/usr/bin/perl use strict; use warnings; use Digest::MD5 qw(md5_hex); my $dir=shift; # 此处默认为检查md5值。 md5check($dir); # 如果需要开始生成web目录的md5值,注释掉上面一句,把下面一句启用 #md5init($dir); sub md5_sum { my ($file_name,$mode)=@_; my ($FD,$ctx, $md5); open ($FD,$file_name) or die "Can't open /'$file_name/': $!"; $ctx = Digest::MD5->new; binmode($FD) if $mode; $ctx->addfile($FD) || die "$!n"; $md5 = $ctx->hexdigest; close $FD; return $md5; } sub md5check { my $file=shift; open(my $fd, '<',$file) or die "$file: $!n"; print $file; while (<$fd>){ my ($name, $sum) = split /s+/; if ($sum eq md5_sum($name,1)){ print "$name OKn"; } else{ print "$name FAILEDn"; } } close $fd; } # 遍历目录计算md5值 sub md5init { my $fd=shift; my $md5value; if ( -f $fd ){ if ( -T $fd ) { #print "按照文本模式进行计算MD5!n"; $md5value =md5_sum($fd,0); print "$fdt$md5valuen"; }elsif( -B $fd ){ #print "二进制文件用binmod计算MD5!n"; $md5value =md5_sum($fd,1); print "$fdt$md5valuen"; }else{ #print "其他文件,按照bimmod计算!n"; $md5value = md5_sum($fd,1); print "$fdt$md5valuen"; } } elsif( -d $fd ){ my $file_md5; # print "开始验证目录下所有文件:n"; opendir (my $DH,$fd) or die "Can't open dir $fd: $!"; for(readdir $DH ){ my $file=$fd.'/'.$_; # 上级目录..,本目录. 以及连接文件跳过 next if ($file =~ m{/.$} || $file =~ m{/..$} || -l $file ); md5chek($file); } closedir $DH; } }
以上程序保存成文件,比如filemd5check.pl
一、生成web的md5文件是时候:
注释掉
#md5check($dir);
md5init($dir);
然后执行 web目录 > webmd5-20160920
web目录换成自己实际的web目录 webmd5-20160920 为保存计算结果的文件,可以自定义
二、检查时候,用默认文件
perl filemd5check.pl webmd5-20160920
]]>
最近又有人挖坑zabbix的sql注入漏洞,此漏洞不在详细说了。此漏洞的利用有个条件必须要登录才行。zabbix如果不做安全配置的话,默认是guest用户空密码可以登录的。
为此写一个脚本检测是否禁用了guest用户,用来批量检查,加固。
use strict; use warnings; use LWP; use Encode; use Data::Dumper; my $lwp = LWP::UserAgent->new; my @url=qw( http://192.168.1/zabbix http://zabbix.ooxx.com http://sb.zabbix.rc/zabbix #... 添加和修改更多的地址 ); for (@url) { my $login_url = $_."/dashboard.php"; print $login_url,":n"; my $respos= $lwp->get($login_url); if ($respos->is_success) { my $res=$respos->content; print "please disable guest accesss!","n" if $res=~/menu_graphs/ms; print "good","n" if $res=~/(<!-- Login Form -->)|(You are not logged in)/ms; } else { print "Login Error: ",$respos->status_line,"n"; } }
上面是是多个地址批量检验的,同时没有兼顾新版本的zabbix,新版可能会报 404错误,下面在发一个检测单url的,同时兼顾新版本zabbix的
use strict; use warnings; use LWP; use Encode; use Data::Dumper; my $url=shift @ARGV; my $lwp = LWP::UserAgent->new; my $login_url1 = $url."/zabbix.php?action=dashboard.view"; my $login_url = $url."/dashboard.php"; my $ok=check($login_url); $ok=check($login_url1) unless $ok; print "Login Error: ","n" unless $ok; sub check { my $url=shift; print $url,":n"; my $respos= $lwp->get($url); if ($respos->is_success) { my $res=$respos->content; print "please disable guest accesss!","n" if $res=~/menu_graphs|initPMaster/ms; print "good","n" if $res=~/(<!-- Login Form -->)|(You are not logged in)/ms; return 1; } else {return 0}; }
使用方法:以上脚本保存为ztest1.pl
然后执行 perl ztest1.pl http://zabbix.org/zabbix
]]>map { code_that_does_something_with( $_ ) } grep { code_that_selects_from( $_ ) } sort { code_that_compares( $a, $b ) } @array
这里我举一个实例来说说明这个变化,有如下的的json数据:
cat dd [{ "createdTime": 11, "versionId": "13a76a74-adc5-4c66-914a-07bb16a486ef" }, { "createdTime": 55, "versionId": "99b26fce-2df8-4364-b13f-3fb89144d64b" }, { "createdTime": 33, "versionId": "4e9ca6a1-1b1d-4586-9ff5-9411330c722d" }, { "createdTime": 44, "versionId": "36859a25-afc4-42c7-bac4-685dc3761c41" }]
要求根据createdTime的值,取最大createdTime值的versionId,我们利用施瓦茨变换的perl单行实现排序,然后取第一行
perl -MJSON -000 -e ' map{ print $_->[2],"n" } sort{ $b->[1] <=> $a->[1] } map{ [$_,$_->{"createdTime"},$_->{"versionId"}]} @{decode_json(<>)}' dd|head 1
相对比用perl脚本实现,取两个值,以createdTime为键,构造一个哈希,然后对哈希进行排序。
#!/bin/env perl use JSON; local $/; open my $FD,'<','dd' or die; my $code = <$FD>; close $FD; my $obj = decode_json($code); my %hash; for(@{$obj}) { $hash{$_->{'createdTime'}}=$_->{'versionId'}; } for (sort keys %hash) { print $hash{$_},"n"; }
]]>
号称可以在一小时扫遍整个互联网,真是名副其实的快扫网。
确保安装了zmap 。centos可以 yum install zmap。
以下为对zmap包装的脚本,保存为scalzmap.pl 。
my $port=shift @ARGV; my $file=shift @ARGV; open $IP,'<',$file or die; my @ip=<$IP>; close $IP; print "Start scan.n"; my %result; my $out=$port.".txt"; open my $OUT,'>',$out or die $!; for (@ip) { next if /(#|$)/; #print $OUT $_ ; my $result=`zmap -p $port $_`; print $OUT $result; print "scan $_ ok!n"; } close $OUT; print "All done.n";
经过我们打包一层后,使用方法 perl zmap.pl 端口 ip.list
端口为一个端口比如 22 ,3306,6379 等 ip.list为要扫描的目标ip地址或者段
格式:
10.2.134.1/24
10.2.123.1/28
等
扫描结果,扫描的结果为端口.txt的ip列表,这个列表的ip表示该端口是通的,这个列表可以用于
之前我们用perl和nmap的扫描器的扫描目的。继续挖掘更多的信息。。。。更多就不说了
创建一个ip列表文件(一个ip一行)all.ip
执行 ./scalport.pl all.ip 开始扫描
结果保存为all.csv
#!/usr/bin/env perl use warnings; use strict; my $filename=shift @ARGV; open my $IN,'<',$filename or die $!; my @ip=<$IN>; my $out; $out=(split /./,$filename)[-1] unless defined $out and $out eq ""; $out=(split /./,$filename)[-2]; $out.=".csv"; my $port=q(80,8080,3306,9200,6379,11211,21,22); my @resul; my $host; print "Start scan.n"; my %result; open my $OUT,'>',$out or die $!; for (@ip) { chomp; next if /(#|$)/; $host=$_; my $result=`nmap -T3 -sV -p $port $_ `; @resul= split /n/ms,$result; for(@resul) { chomp; next if /^$/; next if /Starting Nmap/; next if /Nmap scan report/; next if /PORT/; next if /filtered/; next if /Host is up/; next if /Service detection performed/; next if /Nmap done:/; next if /service unrecognized/; next if /SF/; next if /Service Info/; my $info="$host $_"; $info =~s/s+/,/g; $info =~s//tcp//g; print $OUT $info."n"; } print "scan $_ ok!n"; } close $OUT;
扫描过程比较长,尤其是当ip较多时候,建议用 screen 执行
扫描结果搜索
显示为open 并且 显示服务名称(比如Tomcat 或者 Mysql) 或者nginx 并有版本显示的需要处理:
x.x.x.x,51366,open,ssh,OpenSSH,5.3,(protocol,2.0)
需要封禁sshd端口
x.x.x.x,3306,open,mysql MySQL 5.6.19
Mysql需要封禁端口
x.x.x.x,8080,open,http,Apache,Tomcat/Coyote,JSP,engine,1.1
Tomcat需要屏蔽版本信息
x.x.x.x,80,open,http,nginx 1.9.4
nginx 有版本信息的需要处理