Using F# for development and devops scripts
https://swlaschin.gitbooks.io/fsharpforfunandprofit/content/posts/low-risk-ways-to-use-fsharp-at-work-2.html
Part 2: Using F# for development and devops scripts 使用 F# 进行开发和 devops 脚本
下一组建议涉及将 F# 用于围绕开发活动的各种脚本:构建、持续集成、部署等。
对于这些类型的小任务,您需要一种带有 REPL 的良好脚本语言。您可以使用 PowerShell、ScriptCS,甚至 Python。但为什么不试一试 F#?
F# 感觉像 Python 一样轻巧(很少或没有类型声明)。
F# 可以访问 .NET 库,包括核心库和通过 NuGet 下载的库。
F# 具有类型提供程序(相对于 PowerShell 和 ScriptCS 的一大优势),可让您轻松访问各种数据源。
所有这一切都以简洁、类型安全的方式进行,还带有智能感知!
以这种方式使用 F# 将允许您和您的开发人员使用 F# 代码来解决实际问题。对于这种低风险方法,经理们不应该有任何抵制——在最坏的情况下,您可以轻松地切换到使用不同的工具。
当然,一个隐藏的好处是,一旦您的开发人员同事有机会使用 F#,他们就会上瘾,并且您离使用 F# 端到端又近了一步!
您可以使用 F# 脚本做什么?
在接下来的几节中,我们将看到 F# 脚本的三个示例:
An F# script to check that a website is responding用于检查网站是否响应的 F# 脚本
An F# script to convert an RSS feed into CSV将 RSS 提要转换为 CSV 的 F# 脚本
An F# script that uses WMI to check the stats of a process使用 WMI 检查进程统计信息的 F# 脚本
当然,你也可以将F#脚本与几乎所有的.NET库集成。下面是其他可以用脚本编写的实用程序的建议:
简单的文件复制、目录遍历和归档(例如日志文件)。如果您使用的是 .NET 4.5或更高版本,则可以使用新的 System.IO.Compression.ZipArchive 类进行压缩和解压缩,而无需第三方库。
使用 JSON 解决问题,无论是已知格式(使用 JSON Type Provider)还是未知格式(使用 JSON 解析器)。
与 GitHub 交互使用 Octokit.
从Excel中提取数据,或在其中操作数据。F#支持COM来做Office自动化,或者你可以使用其中一个类型提供者或库。
使用 Math.NET 进行数学计算
Web 抓取、链接检查和屏幕抓取。内置的异步工作流和代理使得这种“多线程”代码非常容易编写。
使用 Quartz.NET 来进行任务调度
如果这些建议激起了您的兴趣,并且您想要更多地使用 F#,请查看 F# 社区项目页面。它是为 F# 编写的有用库的重要来源,其中大部分都可以很好地与 F# 脚本一起使用。
Debug F# 脚本
使用 F# 脚本的一个好处是您不需要创建整个项目,也不需要启动 Visual Studio。
但是,如果您需要调试脚本,而你也不使用 Visual Studio ,那该怎么办呢?以下是一些提示:
首先可以尝试用
printf把内容打印到console里,通常而言我会做一个简单的log函数来 warp 它,这样就可以简单的通过flag来控制是否开启打印你可以使用FsEye工具来检查和观察交互式会话中的变量。(译:这个工具不一定能用了,看了一下最近更新是 Oct. 18, 2016)
最后,你仍然可以使用Visual Studio调试器。诀窍是将调试器附加到fsi.exe进程中,然后你可以使用Debugger.Break在某一点上停止。
5. 将 FAKE 用于构建和 CI 脚本
这部分的代码在 available on github.
让我们从 FAKE 开始,它是一个用 F# 编写的跨平台构建自动化工具,类似于 Ruby 的 Rake。
FAKE 内置了对 git、NuGet、单元测试、Octopus Deploy、Xamarin 等的支持,可以轻松开发具有依赖关系的复杂脚本。
您甚至可以将它与 TFS 一起使用以避免使用 XAML。
使用 FAKE 而不是类似 Rake 的原因之一是您可以在整个工具链中标准化 .NET 代码。理论上,你可以用NAnt来代替,但实际上,不用了,因为XML。PSake也是一种可能性,但我认为比FAKE更复杂。
您还可以使用 FAKE 删除特定构建服务器上的依赖项。例如,与其使用 TeamCity 的集成来运行测试和其他任务,不如考虑在 FAKE 中执行它们,这意味着您可以在不安装 TeamCity 的情况下运行完整构建。
这是一个非常简单的 FAKE 脚本示例,摘自 FAKE 站点上更详细的示例。
// Include Fake lib
// Assumes NuGet has been used to fetch the FAKE libraries
#r "packages/FAKE/tools/FakeLib.dll"
open Fake
// Properties
let buildDir = "./build/"
// Targets
Target "Clean" (fun _ ->
CleanDir buildDir
)
Target "Default" (fun _ ->
trace "Hello World from FAKE"
)
// Dependencies
"Clean"
==> "Default"
// start build
RunTargetOrDefault "Default"语法需要一点时间来适应,但这种努力是值得的。
关于 FAKE 的进一步材料:
Hanselman on FAKE. Many of the comments are from people who are using FAKE actively.
6. 用于检查网站是否响应的 F# 脚本
这部分的代码 available on github.
此脚本检查网站是否以 200 响应。例如,这可能用作部署后的 smoke test 的基础。
// Requires FSharp.Data under script directory
// nuget install FSharp.Data -o Packages -ExcludeVersion
#r @"Packages\FSharp.Data\lib\net40\FSharp.Data.dll"
open FSharp.Data
let queryServer uri queryParams =
try
let response = Http.Request(uri, query=queryParams, silentHttpErrors = true)
Some response
with
| :? System.Net.WebException as ex -> None
let sendAlert uri message =
// send alert via email, say
printfn "Error for %s. Message=%O" uri message
let checkServer (uri,queryParams) =
match queryServer uri queryParams with
| Some response ->
printfn "Response for %s is %O" uri response.StatusCode
if (response.StatusCode <> 200) then
sendAlert uri response.StatusCode
| None ->
sendAlert uri "No response"
// test the sites
let google = "http://google.com", ["q","fsharp"]
let bad = "http://example.bad", []
[google;bad]
|> List.iter checkServer结果是:
Response for http://google.com is 200
Error for http://example.bad. Message=No response请注意,我在 Fsharp.Data 中使用 Http 实用程序代码,它提供了一个很好的 HttpClient 客户端。 更多关于 HttpUtilities 的信息。
7. 将 RSS 流转换为 CSV 的 F# 脚本
The code for this section is available on github.
下面是一个使用 Xml 类型提供程序解析 RSS 提要(在本例中为 StackOverflow 上的 F# 问题)并将其转换为 CSV 文件以供以后分析的小脚本。
请注意,RSS解析代码只有一行代码! 大部分的代码都是关于写CSV的。是的,我可以使用一个CSV库(NuGet上有很多),但我想我应该让它保持原样,向你展示它是多么简单。
// sets the current directory to be same as the script directory
System.IO.Directory.SetCurrentDirectory (__SOURCE_DIRECTORY__)
// Requires FSharp.Data under script directory
// nuget install FSharp.Data -o Packages -ExcludeVersion
#r @"Packages\FSharp.Data\lib\net40\FSharp.Data.dll"
#r "System.Xml.Linq.dll"
open FSharp.Data
type Rss = XmlProvider<"http://stackoverflow.com/feeds/tag/f%23">
// prepare a string for writing to CSV
let prepareStr obj =
obj.ToString()
.Replace("\"","\"\"") // replace single with double quotes
|> sprintf "\"%s\"" // surround with quotes
// convert a list of strings to a CSV
let listToCsv list =
let combine s1 s2 = s1 + "," + s2
list
|> Seq.map prepareStr
|> Seq.reduce combine
// extract fields from Entry
let extractFields (entry:Rss.Entry) =
[entry.Title.Value;
entry.Author.Name;
entry.Published.ToShortDateString()]
// write the lines to a file
do
use writer = new System.IO.StreamWriter("fsharp-questions.csv")
let feed = Rss.GetSample()
feed.Entries
|> Seq.map (extractFields >> listToCsv)
|> Seq.iter writer.WriteLine
// writer will be closed automatically at the end of this scope请注意,类型提供程序会生成智能感知(如下所示)以根据提要的实际内容向您显示可用的属性。这很酷。

结果是这样的:
"Optimising F# answer for Euler #4","DropTheTable","18/04/2014"
"How to execute a function, that creates a lot of objects, in parallel?","Lawrence Woodman","01/04/2014"
"How to invoke a user defined function using R Type Provider","Dave","19/04/2014"
"Two types that use themselves","trn","19/04/2014"
"How does function [x] -> ... work","egerhard","19/04/2014"有关 XML 类型提供程序的更多信息,请见 FSharp.Data 页面.
8. 使用 WMI 检查进程统计信息的 F# 脚本
The code for this section is available on github.
如果您使用 Windows,那么能够访问 WMI 将非常有用。幸运的是,WMI 有一个 F# 类型的提供程序,可以轻松使用它。
在此示例中,我们将获取系统时间并检查进程的一些统计信息。例如,这在负载测试期间和之后可能很有用。
// sets the current directory to be same as the script directory
System.IO.Directory.SetCurrentDirectory (__SOURCE_DIRECTORY__)
// Requires FSharp.Management under script directory
// nuget install FSharp.Management -o Packages -ExcludeVersion
#r @"System.Management.dll"
#r @"Packages\FSharp.Management\lib\net40\FSharp.Management.dll"
#r @"Packages\FSharp.Management\lib\net40\FSharp.Management.WMI.dll"
open FSharp.Management
// get data for the local machine
type Local = WmiProvider<"localhost">
let data = Local.GetDataContext()
// get the time and timezone on the machine
let time = data.Win32_UTCTime |> Seq.head
let tz = data.Win32_TimeZone |> Seq.head
printfn "Time=%O-%O-%O %O:%O:%O" time.Year time.Month time.Day time.Hour time.Minute time.Second
printfn "Timezone=%O" tz.StandardName
// find the "explorer" process
let explorerProc =
data.Win32_PerfFormattedData_PerfProc_Process
|> Seq.find (fun proc -> proc.Name.Contains("explorer") )
// get stats about it
printfn "ElapsedTime=%O" explorerProc.ElapsedTime
printfn "ThreadCount=%O" explorerProc.ThreadCount
printfn "HandleCount=%O" explorerProc.HandleCount
printfn "WorkingSetPeak=%O" explorerProc.WorkingSetPeak
printfn "PageFileBytesPeak=%O" explorerProc.PageFileBytesPeak输出是这样的:
Time=2014-4-20 14:2:35
Timezone=GMT Standard Time
ElapsedTime=2761906
ThreadCount=67
HandleCount=3700
WorkingSetPeak=168607744
PageFileBytesPeak=312565760同样,使用类型提供程序意味着您可以获得智能感知(如下所示)。对于数百个 WMI 选项非常有用。

有关 WMI 类型提供程序的更多信息,请参见此处。More on the WMI type provider here.
9. 使用 F# 配置和管理云
一个值得特别提及的领域是使用 F# 来配置和管理云服务。 fsharp.org 上的云页面有许多有用的链接。
对于简单的脚本,Fog 是 Azure 的一个很好的封装。
因此,例如,要上传一个 blob,代码就这么简单:
UploadBlob "testcontainer" "testblob" "This is a test" |> ignore或添加和接收消息:
AddMessage "testqueue" "This is a test message" |> ignore
let result = GetMessages "testqueue" 20 5
for m in result do
DeleteMessage "testqueue" m为此使用 F# 的特别好处是您可以在微型脚本中完成——您不需要任何繁重的工具。
总结
我希望你觉得这些建议有用。如果您在实践中应用它们,请在评论中告诉我。
接下来:使用 F# 进行测试。
Last updated