golang挂载网盘
问题
前段时间用的python和nodejs做了一些web的事情,主要用于显示和封装后端的一些指令。最近在学习golang,所以,看到有需求了,就想用golang来实现。
问题是golang的轮子不是很多,找起来比较麻烦,所以尽可能用系统内置的一些指令来执行最好。
下面用挂载网络盘这个最简单的需求来说,怎么样用golang的os.exec模块来实现。
过程
- 第一步是对用户进行身份验证,确保他的账户和密码输入是正确的
- 此时需要调用身份验证的模块,这里有两个选择,第一个是用ldap的方式进行验证,一个是使用smb的方式进行验证
- 因为这个挂载的是smb的,所以就选择smb的方式进行验证了,当然这两个选择哪个都是没有任何问题的,这里以smb为例了
- 调用windows的内置挂在网络盘的命令
- 这里同样有两种方式,一种就是net use的,这个最简单,还有就是使用powershell的方式
- powershell的方式在这个例子里面也包括,所以怎么用powershell的方式来进行挂载你也可以自己试试,这里以net use的方式来说明
- 给出成功/失败/错误的信息给管理者
- 这个是个可选的,不过我还是做了。通过邮件的方式来实现。将输出信息发送邮件给管理者,确定谁在什么时候是否访问了他的网络盘
- 最近喜欢搞一些监控类的小东西,所以很多时候都写了邮件通告的部分,可以直接拿来就用
好了,前面的思考部分结束,开始代码部分:
package main
import (
"fmt"
"log"
"os/exec"
"syscall"
"time" //发送邮件的时候用来确定时间的
"github.com/stacktitan/smb/smb" //这个就是说的用来做smb验证的
"golang.org/x/crypto/ssh/terminal" //这个是用来确保在console输入的密码安全的
ps "github.com/bhendo/go-powershell" //这个是调用powershell的指令的
"github.com/bhendo/go-powershell/backend"
"gopkg.in/gomail.v2" //这个是用来发送邮件的
)
验证部分:
func createsession(username, password string) {
host := "fileserver.domain.com"
options := smb.Options{
Host: host,
Port: 445,
User: username,
Domain: "domain",
Workstation: "",
Password: password,
}
debug := false
session, err := smb.NewSession(options, debug)
if err != nil {
log.Fatalln("[!]", err)
}
//defer session.Close() //这里我将这条给注释掉了,其实是不应该的。我们的目的仅仅是验证用户名和密码,并不需要做其他的事情。
if session.IsAuthenticated {
log.Println("[+] Login successful")
} else {
log.Println("[-] Login failed")
}
if err != nil {
log.Fatalln("[!]", err)
}
}
挂载部分:
这段才是我要说的重点,虽然做了后觉得没什么大不了的,可是当第一次做的时候,还是有点不对劲,我当时用引号的方式,以及``的方式总是得出错误的结果,后来换成和python一样的用arrary的方式,就是ok了。
func mountfolder(username,password string){
//net use 挂载
cmd:=`net`
args:=[]string{`use`,"P:",`\\fileserver.domain.com\`+username,`/User:`+`domain\`+username,password}
mount:=exec.Command(cmd,args...)
if err:=mount.Run();err!=nil{
log.Fatal(err)
}
//利用powershell修改挂载的名字,让好看点
back:=&backend.Local{}
shell,err:=ps.New(back)
defer shell.Exit()
stdout, _, err := shell.Execute(`(New-Object -com shell.application).namespace('P:').self.name='Personal'`)
if err != nil {
log.Fatal(err)
}
//调取exploer直接打开这个P盘
cmd0:=exec.Command(`explorer`,`P:`)
cmd0.Run() //这里不在设定err返回的东西
}
根据返回的code值发送通告:
func alertmail(username, code string) {
etime := time.Now().Format(time.RFC850)
//send email to owner about new file created and write
m := gomail.NewMessage()
m.SetHeader("From", "Personal_folder_access@domain.com")
m.SetHeader("To", "xxx@domain.com")
m.SetAddressHeader("Bcc", "YYY@domain.com", "Mark")
m.SetHeader("Subject", "Personal Folder Access alert")
switch code {
case "not exist":
m.SetBody("text/html", "<b>Alert</b>\n"+etime+"----"+username+"---"+"Personal Folder does not exist!")
case "success":
m.SetBody("text/html", "<b>Alert</b>\n"+etime+"----"+username+"---"+"Access the Personal Folder")
default:
m.SetBody("text/html", "<b>Alert</b>\n"+etime+"----"+username+"---"+"try to access the personl folder")
}
d := gomail.NewDialer("smtp.domain.com", 25, "", "")
if err := d.DialAndSend(m); err != nil {
log.Fatal(err)
}
收尾部分
基本的主要程序部分就是这样的,其实在windows里面就那么一句话而已,但是既然是做programmer,还是用程序的思维来的比较顺一些。最后用go build生成exe,试了下,没问题。为了美观,可以借鉴下面的这个链接来实现添加icon以及添加版本信息,作者等的属性给到exe程序。
embedded-icon-in-go-windows-application
总结
这段时间对于golang的使用算是婴儿期,知道了一些语法,使用上面还没有很熟练,但是总的来说golang更多的在后端系统层面是很优秀的,尤其对于信号通告以及多进程的使用上面。这个要比其他的预言好很多,系统的阻塞基本上都可以排除了。nodejs在web层面的nonblock也很棒,但是nodejs在系统编程方面不是很合适,python的主要问题是如果你做了个小程序,发出去后基本上是明文的。而且python的自身要依靠系统的,或者第三方的应用才能发挥出来。
每种语言都有比较合适的用于处理问题的方式,不同的问题,用不同的语言来搞定会更明智一些。这个只是一个例子,并不应该是真正的处理问题的方式。
加油!!!