设为首页 收藏本站
查看: 970|回复: 0

How to learn powershell from zero-Security

[复制链接]

尚未签到

发表于 2018-9-3 07:15:09 | 显示全部楼层 |阅读模式
  How to create and build an powershell script  with windows ?
  1.create an script of shell.
  在PowerShell中不存在文件和目录的概念,涉及文件和目录的操作总是转换为项(item)处理,即Get-Item、Get-ChildItem和Get-ItemProperty。在PowerShell中的dir命令以Get-ChildItem的别名出现,通过项操作对象的原因是PowerShell作用的任何类型的对象均以项的形式存在。而不像类Unix系统中将所有的对象都抽象成文件,即使这个对象很明显不是文件的情况。
  项是包含内容的属性对象,这些对象又可以包含其他项。这个定义可以很容易扩展到文件和目录,即它们是具有各自内容和属性的项。项的概念可以应用于多个系统对象,提供程序(provider)用来创建、找回、修改和移除项。它是官方提供的重要的Shell扩展机制之一,Shell与一些内置的提供程序一起发布给用户,其中提供了提供程序的接口。
  1 创建脚本
  典型的PowerShell脚本是文本类型的文件,可以使用任何文本编辑器来创建。通常情况下,具有.ps1的文件后缀。最好使用一些语法高亮,甚至是智能补全功能的编辑器,如创建本书中脚本文件的Notepad++编辑器。这是一个功能强大的编辑器,支持多种语言,并且提供语法高亮及关键字补全等;另外可以在PowerShell控制台下使用Set-Content这个cmdlet来创建脚本文件。下面使用该命令创建一个脚本文件:
  PS C:\> $code = @" >> Write-Host "Hello World!!" >> "@ >> PS C:\> Set-Content hello-world.ps1 $code PS C:\> type hello-world.ps1 Write-Host "Hello World!!"
  
  hello-world.ps1以普通的文本文件形式存在,可以使用type命令(以Get-Content命令的别名存在)来查看其内容。
  1.1 调用脚本
  在PowerShell中调用脚本文件时应在PATH环境变量中包含的路径中搜索,当前目录并不在系统的PATH中。调用当前目录中的脚本文件需要添加前缀,调用当前的脚本文件的方式应该是.\hello-world.ps1。
  如果当前目录默认包含在PATH中,则允许***者采用恶意代码覆盖同名的默认程序。假设恶意用户在共享目录中写入与内置cmdlet同名的脚本,当管理员访问这个共享目录时并调用了该脚本,则可导致恶意操作。因此在PowerShell和Unix的Shell中需要用户通过在当前路径前增加.\前缀,显式地指明需要执行当前目录中的程序。
  调用创建的hello-world.ps1脚本文件提示以下错误:
  PS C:\> .\hello-world.ps1 File C:\hello-world.ps1 cannot be loaded because the execution of scripts is disabled on this system. Please see "get-help about_signing" for more details. At line:1 char:18 + .\hello-world.ps1  Get-ExecutionPolicy RemoteSigned
  
  下例调用本地脚本文件:
  PS C:\> .\hello-world.ps1 Hello World!!
  
  另外脚本块执行操作符(&)也可执行脚本文件:
  PS C:\> & .\hello-world.ps1 Hello World!! PS C:\> & .\hello-world Hello World!!
  
  1.2 传递参数
  脚本能够接收参数,这样可以针对不同对象执行所需操作。脚本文件支持$args变量,用于在执行时接收传递的参数。下例在指定目录中查找文件名符合指定通配符的文件:
  $where = $args[0] $what = $args[1] if(!$what -match "\.wma$") { $what = $what + ".wma" } Get-ChildItem $where $what –Recurse
  
  $what参数用来在通配符不包含.wma扩展名时添加扩展名,从而限制搜索文件的范围只限于.wma文件。代码递归遍历所有文件,并返回符合$what通配符的文件。将以上代码保存为Get-Music.ps1脚本文件,其中查找名为“ A Place Near by.wma”的音乐文件:
  PS C:\> .\Get-Music.ps1 'D:\Music' *Near* Directory: D:\Music Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 2009/3/1 20:38 3006849 A Place Near by.wma
  
  脚本文件允许使用param语句定义自己的参数名,以避免$args参数对象要求输入参数的顺序必须与预定义顺序一致。下例用命名参数方式重写前面的脚本文件,并命名为“Get-Music-Param.ps1”:
  param ($where,$what) if(!$what -match "\.wma$") { $what = $what + ".wma" } Get-ChildItem $where $what –Recurse
  
  其中的参数允许在不限制输入参数顺序的情况下调用脚本文件,下面调用该脚本文件查找名为“Dont You Forget.wma”的音乐文件:
  PS C:\> .\Get-Music-Param.ps1 -where 'D:\Music' -what *You* Directory: D:\Music Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 2009/3/1 21:19 3556057 Dont You Forget.wma
  
  通过定义begin、process和end块来实现在管道命令中输入,下例获取文件序列并过滤掉所有大于指定大小的文件,将代码保存为FileSize-FilterLarge.ps1脚本:
  param ($sizeLimit) begin { } process { if($_.Length -ge $sizeLimit) { $_ } } end { }
  
  脚本文件接收文件大小变量用于后面检测所有管道命令传递项的大小,最后返回文件长度等于大小限制的文件。实例中的所有操作在process块中执行,当调用代码块时会作用于管道输入的所有项。begin和end块未执行任何操作,但是为了代码的完整性和可读性,总是习惯性地包含它们,即使其为空。下例使用脚本文件查找小于13个字节的文件:
  PS C:\> dir *.txt | .\FileSize-FilterLarge.ps1 13 Directory: C:\ Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 2009/1/3 14:31 12 digit.txt -ar-- 2009/1/3 6:27 13 test.txt -a--- 2009/1/3 6:28 9 test2.txt
  
  与函数相似,脚本文件会创建独立的变量作用域。即可读入由当前shell环境及其父作用域中的变量,对同名变量的写入会在当前作用域下覆盖父作用域中的值。下面创建一个访问父作用域的脚本文件:
  PS C:\> $name = "LiMing" PS C:\> Set-Content Variable-Scope.ps1 "Write-Host $name" PS C:\> .\Variable-Scope.ps1 LiMing
  
  接下来演示如果在脚本文件中修改外部已经初始化的变量,是否会更改该变量的值,将以下代码保存为“Variable-ScopeInnerVariable.ps1”文件:
  Write-Host "Variable Within script original: $name" $name = "XiaoGang" Write-Host "Variable Within script modified: $name"
  
  调用这个脚本文件验证原有变量的内容:
  PS C:\> $name = "LiMing" PS C:\> .\Variable-ScopeInnerVariable.ps1 Variable Within script original: LiMing Variable Within script modified: XiaoGang PS C:\> Write-Host "Variable Outside of script $name" Variable Outside of script LiMing
  
  可以看出修改变量的操作只在脚本文件内部起作用,如果需要在脚本文件内部修改父作用域中的变量,则在脚本文件中使用$global作用域前缀或者Get-Variable/Set-Variable这类cmdlet显式要求修改父作用域变量。下例在脚本文件内使用$global关键字修改父作用域变量:
  Write-Host "Variable Within script original: $global:name" $global:name = "XiaoGang" Write-Host "Variable Within script modified: $global:name"
  
  将上述代码保存为“Variable-ModifyGloablVariable.ps1”文件,调用该文件时的提示如下:
  PS C:\> $name = "LiMing" PS C:\> .\Variable-ModifyGloablVariable.ps1 Variable Within script original: LiMing Variable Within script modified: XiaoGang PS C:\> Write-Host "Variable outside script :$global:name" Variable outside script :XiaoGang
  
  有时需要隔离特定的变量或函数,对于特定的脚本文件来说它是全局的。需要让其中定义的所有函数和脚本块能够访问该变量或函数,但用户需要显式强调不能在脚本文件外访问对象。这时不能使用$global作用域前缀,因为这将使该变量或函数暴露在所有代码面,无论它们是否已在脚本文件中定义。解决这个问题的方法是使用$script作用域前缀,为了说明这个问题,建立如下脚本文件代码:
  $script:name = "LiuTao" function Modify-Name() { $script:name = "XiaoGang" Write-Host "Variable within script function scope:$script:name" } Write-Host "Variable Original script global scope: $script:name" Modify-Name Write-Host "Variable Modified script global scope: $script:name"
  
  上述代码中存在脚本全局作用域和Modify-Name函数作用域,在shell可以通过引用$script:name调用脚本全局变量。将以上脚本另存为“Variable-ScriptScope.ps1”文件并调用:
  PS C:\> $name = "LiMing" PS C:\> .\Variable-ScriptScope.ps1 Variable Original script global scope: LiuTao Variable within script function scope:XiaoGang Variable Modified script global scope: XiaoGang PS C:\> Write-Host "Variable outeside of script: $name" Variable outeside of script: LiMing
  
  能够看到对于脚本文件以外的$name变量并没有受到影响。
  与此相对应,通过在脚本文件名前增加点(.)前缀来实现脚本文件访问所有的当前变量和函数,即将脚本文件点源引用(dot-sourcing)到当前shell进程中。点源引用使用点加空格再加上要引用的脚本文件名,将该脚本文件的所有变量、函数、脚本块释放在当前shell中供使用。下例以点源引用的方式来调用Variable-ScriptScope.ps1脚本文件:
  PS C:\> $name = "LiMing" PS C:\> . .\Variable-ScriptScope.ps1 Variable Original script global scope: LiuTao Variable within script function scope:Mike Variable Modified script global scope: Mike PS C:\> Write-Host "Variable outeside of script: $name" Variable outeside of script: Mike
  
  由于使用了点源引用方式来调用同一个脚本文件,因此结果与之前不同,即修改了全局变量$name的值。
  1.3 返回值
  在大多数情况下,参数是外部世界传递数据到脚本文件的唯一通信机制。在脚本文件处理数据之后需要将结果返回给外部,在PowerShell中提供了很好的实现方法。
  如果没有显式销毁、赋值给变量、管道输出或重定向到其他命令对象,则将会为下个命令输出到管道中,可以通过脚本生成一系列的对象并输出。下例输出3个缓存文件名:
  PS C:\> $code = @" >> "File1.tmp" >> "File2.tmp" >> "File3.tmp" >> "@ >> PS C:\> Set-Content Generate-TempFiles.ps1 $code PS C:\> $files = .\Generate-TempFiles.ps1 PS C:\> $files File1.tmp File2.tmp File3.tmp PS C:\> .\Generate-TempFiles.ps1 | foreach{"File:" + $_ } File:File1.tmp File:File2.tmp File:File3.tmp
  
  既可将对象赋给变量,也可传递到管道中的下一个命令。
  下例中的return语句返回现有对象,并终止后续代码:
  PS C:\> $code = @" >> return "File1.tmp" >> return "File2.tmp" >> "@ >> PS C:\> Set-Content Generate-TempFilesReturn.ps1 $code PS C:\> .\Generate-TempFilesReturn.ps1 File1.tmp
  
  代码在第1个return语句之后终止,因而只输出一个文件对象。
  如果是运行在顶层作用域中,return语句会退出脚本文件,但是上述代码中该语句只是退出当前作用域。即如果return语句是在脚本文件中的脚本块或函数中,只是退出该脚本块或函数,而脚本文件本身还将继续执行。为了显式退出脚本文件,需要使用exit语句。下例在脚本文件中的函数中退出整个脚本文件的执行:
  function Verify-TextFile($file) { if(!$file.EndsWith(".txt")) { Write-Host "$file is not a text file" exit } } $files = "Names.txt","Music.wma","Photo.jpg" foreach($file in $files) { Verify-TextFile $file }
  
  将文件另存为“Explicit-Exit.ps1”,然后调用如下:
  PS C:\> .\Explicit-Exit.ps1 Music.wma is not a text file
  
  可以看到未执行检测Photo.jpg文件的操作,而是在检测Music.wma文件后退出。
  2 从其他环境中执行脚本
  PowerShell代码与已经存在的解决方案结合,才能发挥最大作用。可以编写所需脚本并在Windows的计划任务中调用,也可以将现有的脚本解决方案逐块转换为用PowerShell开发,或者用命令方式调用现有解决方案。所有自动化环境,包括任务计划服务、软件系统,以及执行外部命令都可以将PowerShell扩展进来。可以调用PowerShell.exe并把脚本块名作为参数:
  C:\>PowerShell.exe hello-world.ps1 The term 'hello-world.ps1' is not recognized as a cmdlet, function, operable pr ogram, or script file. Verify the term and try again. At line:1 char:16 + hello-world.ps1  .\Lib-User-DotSource.ps1 The term '.\Library.ps1' is not recognized as a cmdlet, function, operable program, or script file. Verify the term and try again. At C:\Lib-User-DotSource.ps1:1 char:2 + .

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-561763-1-1.html 上篇帖子: Powershell_Script<3> 下篇帖子: Powershell_Script<4>
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表