SSH密码、密钥从文件中读取
parent
741bee1392
commit
72499731f3
2
build.sh
2
build.sh
|
@ -86,6 +86,8 @@ done
|
||||||
rm -rf $TEMP_DIR/$APP_NAME/conf/*
|
rm -rf $TEMP_DIR/$APP_NAME/conf/*
|
||||||
rm -rf $TEMP_DIR/$APP_NAME/log/*
|
rm -rf $TEMP_DIR/$APP_NAME/log/*
|
||||||
rm -rf $TEMP_DIR/$APP_NAME/data/sessions/*
|
rm -rf $TEMP_DIR/$APP_NAME/data/sessions/*
|
||||||
|
rm -rf $TEMP_DIR/$APP_NAME/data/password/*
|
||||||
|
rm -rf $TEMP_DIR/$APP_NAME/data/private_key/*
|
||||||
|
|
||||||
echo '压缩文件'
|
echo '压缩文件'
|
||||||
# 压缩文件
|
# 压缩文件
|
||||||
|
|
12
cmd/web.go
12
cmd/web.go
|
@ -9,6 +9,8 @@ import (
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
"github.com/ouqiang/gocron/modules/logger"
|
"github.com/ouqiang/gocron/modules/logger"
|
||||||
|
"github.com/ouqiang/gocron/service"
|
||||||
|
"github.com/ouqiang/gocron/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
// web服务器默认端口
|
// web服务器默认端口
|
||||||
|
@ -37,6 +39,8 @@ func run(ctx *cli.Context) {
|
||||||
setEnvironment(ctx)
|
setEnvironment(ctx)
|
||||||
// 初始化应用
|
// 初始化应用
|
||||||
app.InitEnv()
|
app.InitEnv()
|
||||||
|
// 初始化模块 DB、定时任务等
|
||||||
|
initModule()
|
||||||
// 捕捉信号,配置热更新等
|
// 捕捉信号,配置热更新等
|
||||||
go catchSignal()
|
go catchSignal()
|
||||||
m := macaron.Classic()
|
m := macaron.Classic()
|
||||||
|
@ -48,6 +52,14 @@ func run(ctx *cli.Context) {
|
||||||
m.Run(port)
|
m.Run(port)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initModule() {
|
||||||
|
models.Db = models.CreateDb()
|
||||||
|
|
||||||
|
// 初始化定时任务
|
||||||
|
serviceTask := new(service.Task)
|
||||||
|
serviceTask.Initialize()
|
||||||
|
}
|
||||||
|
|
||||||
// 解析端口
|
// 解析端口
|
||||||
func parsePort(ctx *cli.Context) int {
|
func parsePort(ctx *cli.Context) int {
|
||||||
var port int = DefaultPort
|
var port int = DefaultPort
|
||||||
|
|
|
@ -3,6 +3,12 @@ package models
|
||||||
import (
|
import (
|
||||||
"github.com/ouqiang/gocron/modules/ssh"
|
"github.com/ouqiang/gocron/modules/ssh"
|
||||||
"github.com/go-xorm/xorm"
|
"github.com/go-xorm/xorm"
|
||||||
|
"github.com/ouqiang/gocron/modules/app"
|
||||||
|
"github.com/ouqiang/gocron/modules/utils"
|
||||||
|
"errors"
|
||||||
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
|
"github.com/ouqiang/gocron/modules/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 主机
|
// 主机
|
||||||
|
@ -11,11 +17,9 @@ type Host struct {
|
||||||
Name string `xorm:"varchar(64) notnull"` // 主机名称
|
Name string `xorm:"varchar(64) notnull"` // 主机名称
|
||||||
Alias string `xorm:"varchar(32) notnull default '' "` // 主机别名
|
Alias string `xorm:"varchar(32) notnull default '' "` // 主机别名
|
||||||
Username string `xorm:"varchar(32) notnull default '' "` // ssh 用户名
|
Username string `xorm:"varchar(32) notnull default '' "` // ssh 用户名
|
||||||
Password string `xorm:"varchar(64) notnull default ''"` // ssh 密码
|
|
||||||
Port int `xorm:"notnull default 22"` // 主机端口
|
Port int `xorm:"notnull default 22"` // 主机端口
|
||||||
Remark string `xorm:"varchar(100) notnull default '' "` // 备注
|
Remark string `xorm:"varchar(100) notnull default '' "` // 备注
|
||||||
AuthType ssh.HostAuthType `xorm:"tinyint notnull default 1"` // 认证方式 1: 密码 2: 公钥
|
AuthType ssh.HostAuthType `xorm:"tinyint notnull default 1"` // 认证方式 1: 密码 2: 公钥
|
||||||
PrivateKey string `xorm:"varchar(4096) notnull default '' "` // 私钥
|
|
||||||
BaseModel `xorm:"-"`
|
BaseModel `xorm:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +34,7 @@ func (host *Host) Create() (insertId int16, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (host *Host) UpdateBean(id int16) (int64, error) {
|
func (host *Host) UpdateBean(id int16) (int64, error) {
|
||||||
return Db.ID(id).Cols("name,alias,username,password,port,remark,auth_type,private_key").Update(host)
|
return Db.ID(id).Cols("name,alias,username,port,remark,auth_type").Update(host)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -83,6 +87,38 @@ func (host *Host) Total(params CommonMap) (int64, error) {
|
||||||
return session.Count(host)
|
return session.Count(host)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Host) GetPasswordByHost(host string) (string, error) {
|
||||||
|
path := app.DataDir + "/ssh/password/" + host
|
||||||
|
|
||||||
|
|
||||||
|
return h.readFile(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Host) GetPrivateKeyByHost(host string) (string,error) {
|
||||||
|
path := app.DataDir + "/ssh/private_key/" + host
|
||||||
|
|
||||||
|
return h.readFile(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (host *Host) readFile(file string) (string, error) {
|
||||||
|
logger.Debug("认证文件路径: ", file)
|
||||||
|
if !utils.FileExist(file) {
|
||||||
|
return "", errors.New(file + "-认证文件不存在或无权限访问")
|
||||||
|
}
|
||||||
|
|
||||||
|
contentByte, err := ioutil.ReadFile(file)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
content := string(contentByte)
|
||||||
|
content = strings.TrimSpace(content)
|
||||||
|
if content == "" {
|
||||||
|
return "", errors.New("密码为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
return content, nil
|
||||||
|
}
|
||||||
|
|
||||||
// 解析where
|
// 解析where
|
||||||
func (host *Host) parseWhere(session *xorm.Session, params CommonMap) {
|
func (host *Host) parseWhere(session *xorm.Session, params CommonMap) {
|
||||||
if len(params) == 0 {
|
if len(params) == 0 {
|
||||||
|
|
|
@ -8,6 +8,9 @@ import (
|
||||||
"gopkg.in/macaron.v1"
|
"gopkg.in/macaron.v1"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"github.com/ouqiang/gocron/modules/logger"
|
||||||
|
"github.com/ouqiang/gocron/modules/setting"
|
||||||
|
"github.com/ouqiang/gocron/modules/app"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Status int8
|
type Status int8
|
||||||
|
@ -60,7 +63,8 @@ func (model *BaseModel) pageLimitOffset() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建Db
|
// 创建Db
|
||||||
func CreateDb(config map[string]string) *xorm.Engine {
|
func CreateDb() *xorm.Engine {
|
||||||
|
config := getDbConfig()
|
||||||
dsn := getDbEngineDSN(config["engine"], config)
|
dsn := getDbEngineDSN(config["engine"], config)
|
||||||
engine, err := xorm.NewEngine(config["engine"], dsn)
|
engine, err := xorm.NewEngine(config["engine"], dsn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -116,3 +120,26 @@ func keepDbAlived(engine *xorm.Engine) {
|
||||||
engine.Ping()
|
engine.Ping()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取数据库配置
|
||||||
|
func getDbConfig() map[string]string {
|
||||||
|
config, err := setting.Read(app.AppConfig)
|
||||||
|
if err != nil {
|
||||||
|
logger.Fatal(err)
|
||||||
|
}
|
||||||
|
section := config.Section("db")
|
||||||
|
if err != nil {
|
||||||
|
logger.Fatal(err)
|
||||||
|
}
|
||||||
|
var db map[string]string = make(map[string]string)
|
||||||
|
db["user"] = section.Key("user").String()
|
||||||
|
db["password"] = section.Key("password").String()
|
||||||
|
db["host"] = section.Key("host").String()
|
||||||
|
db["port"] = section.Key("port").String()
|
||||||
|
db["database"] = section.Key("database").String()
|
||||||
|
db["charset"] = section.Key("charset").String()
|
||||||
|
db["prefix"] = section.Key("prefix").String()
|
||||||
|
db["engine"] = section.Key("engine").String()
|
||||||
|
|
||||||
|
return db
|
||||||
|
}
|
|
@ -40,10 +40,8 @@ type TaskHost struct {
|
||||||
Name string
|
Name string
|
||||||
Port int
|
Port int
|
||||||
Username string
|
Username string
|
||||||
Password string
|
|
||||||
Alias string
|
Alias string
|
||||||
AuthType ssh.HostAuthType
|
AuthType ssh.HostAuthType
|
||||||
PrivateKey string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (TaskHost) TableName() string {
|
func (TaskHost) TableName() string {
|
||||||
|
@ -87,7 +85,7 @@ func (task *Task) Enable(id int) (int64, error) {
|
||||||
// 获取所有激活任务
|
// 获取所有激活任务
|
||||||
func (task *Task) ActiveList() ([]TaskHost, error) {
|
func (task *Task) ActiveList() ([]TaskHost, error) {
|
||||||
list := make([]TaskHost, 0)
|
list := make([]TaskHost, 0)
|
||||||
fields := "t.*, host.alias,host.name,host.username,host.password,host.port,host.auth_type,host.private_key"
|
fields := "t.*, host.alias,host.name,host.username,host.port,host.auth_type"
|
||||||
err := Db.Alias("t").Join("LEFT", hostTableName(), "t.host_id=host.id").Where("t.status = ?", Enabled).Cols(fields).Find(&list)
|
err := Db.Alias("t").Join("LEFT", hostTableName(), "t.host_id=host.id").Where("t.status = ?", Enabled).Cols(fields).Find(&list)
|
||||||
|
|
||||||
return list, err
|
return list, err
|
||||||
|
@ -96,7 +94,7 @@ func (task *Task) ActiveList() ([]TaskHost, error) {
|
||||||
// 获取某个主机下的所有激活任务
|
// 获取某个主机下的所有激活任务
|
||||||
func (task *Task) ActiveListByHostId(hostId int16) ([]TaskHost, error) {
|
func (task *Task) ActiveListByHostId(hostId int16) ([]TaskHost, error) {
|
||||||
list := make([]TaskHost, 0)
|
list := make([]TaskHost, 0)
|
||||||
fields := "t.*, host.alias,host.name,host.username,host.password,host.port,host.auth_type,host.private_key"
|
fields := "t.*, host.alias,host.name,host.username,host.port,host.auth_type"
|
||||||
err := Db.Alias("t").Join("LEFT", hostTableName(), "t.host_id=host.id").Where("t.status = ? AND t.host_id = ?", Enabled, hostId).Cols(fields).Find(&list)
|
err := Db.Alias("t").Join("LEFT", hostTableName(), "t.host_id=host.id").Where("t.status = ? AND t.host_id = ?", Enabled, hostId).Cols(fields).Find(&list)
|
||||||
|
|
||||||
return list, err
|
return list, err
|
||||||
|
@ -122,7 +120,7 @@ func (task *Task) NameExist(name string, id int) (bool, error) {
|
||||||
|
|
||||||
func(task *Task) Detail(id int) (TaskHost, error) {
|
func(task *Task) Detail(id int) (TaskHost, error) {
|
||||||
taskHost := TaskHost{}
|
taskHost := TaskHost{}
|
||||||
fields := "t.*, host.alias,host.name,host.username,host.password,host.port,host.auth_type,host.private_key"
|
fields := "t.*, host.alias,host.name,host.username,host.port,host.auth_type"
|
||||||
_, err := Db.Alias("t").Join("LEFT", hostTableName(), "t.host_id=host.id").Where("t.id=?", id).Cols(fields).Get(&taskHost)
|
_, err := Db.Alias("t").Join("LEFT", hostTableName(), "t.host_id=host.id").Where("t.id=?", id).Cols(fields).Get(&taskHost)
|
||||||
|
|
||||||
return taskHost, err
|
return taskHost, err
|
||||||
|
|
|
@ -3,11 +3,9 @@ package app
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/ouqiang/gocron/models"
|
|
||||||
"github.com/ouqiang/gocron/service"
|
|
||||||
"github.com/ouqiang/gocron/modules/setting"
|
|
||||||
"github.com/ouqiang/gocron/modules/logger"
|
"github.com/ouqiang/gocron/modules/logger"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"github.com/ouqiang/gocron/modules/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -33,10 +31,6 @@ func InitEnv() {
|
||||||
AppConfig = ConfDir + "/app.ini"
|
AppConfig = ConfDir + "/app.ini"
|
||||||
checkDirExists(ConfDir, LogDir, DataDir)
|
checkDirExists(ConfDir, LogDir, DataDir)
|
||||||
Installed = IsInstalled()
|
Installed = IsInstalled()
|
||||||
if Installed {
|
|
||||||
InitDb()
|
|
||||||
InitResource()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断应用是否安装过
|
// 判断应用是否安装过
|
||||||
|
@ -59,51 +53,11 @@ func CreateInstallLock() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化资源
|
|
||||||
func InitResource() {
|
|
||||||
// 初始化定时任务
|
|
||||||
serviceTask := new(service.Task)
|
|
||||||
serviceTask.Initialize()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化DB
|
|
||||||
func InitDb() {
|
|
||||||
dbConfig := getDbConfig(AppConfig)
|
|
||||||
models.Db = models.CreateDb(dbConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检测目录是否存在
|
// 检测目录是否存在
|
||||||
func checkDirExists(path ...string) {
|
func checkDirExists(path ...string) {
|
||||||
for _, value := range path {
|
for _, value := range path {
|
||||||
_, err := os.Stat(value)
|
if !utils.FileExist(value) {
|
||||||
if os.IsNotExist(err) {
|
logger.Fatal(value + "目录不存在或无权限访问")
|
||||||
logger.Fatal(value + "目录不存在")
|
|
||||||
}
|
|
||||||
if os.IsPermission(err) {
|
|
||||||
logger.Fatal(value + "目录无权限操作")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取数据库配置
|
|
||||||
func getDbConfig(configFile string) map[string]string {
|
|
||||||
config, err := setting.Read(configFile)
|
|
||||||
if err != nil {
|
|
||||||
logger.Fatal(err)
|
|
||||||
}
|
|
||||||
section := config.Section("db")
|
|
||||||
if err != nil {
|
|
||||||
logger.Fatal(err)
|
|
||||||
}
|
|
||||||
var db map[string]string = make(map[string]string)
|
|
||||||
db["user"] = section.Key("user").String()
|
|
||||||
db["password"] = section.Key("password").String()
|
|
||||||
db["host"] = section.Key("host").String()
|
|
||||||
db["port"] = section.Key("port").String()
|
|
||||||
db["database"] = section.Key("database").String()
|
|
||||||
db["charset"] = section.Key("charset").String()
|
|
||||||
db["prefix"] = section.Key("prefix").String()
|
|
||||||
db["engine"] = section.Key("engine").String()
|
|
||||||
|
|
||||||
return db
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"github.com/Tang-RoseChild/mahonia"
|
"github.com/Tang-RoseChild/mahonia"
|
||||||
"strings"
|
"strings"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -106,3 +107,15 @@ func EscapeJson(s string) string {
|
||||||
|
|
||||||
return ReplaceStrings(s, specialChars, replaceChars)
|
return ReplaceStrings(s, specialChars, replaceChars)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FileExist(file string) bool {
|
||||||
|
_, err := os.Stat(file)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if os.IsPermission(err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
|
@ -64,15 +64,28 @@ func Ping(ctx *macaron.Context) string {
|
||||||
return json.CommonFailure("主机不存在", err)
|
return json.CommonFailure("主机不存在", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
sshConfig := ssh.SSHConfig{
|
sshConfig := ssh.SSHConfig{}
|
||||||
User: hostModel.Username,
|
sshConfig.User = hostModel.Username
|
||||||
Password: hostModel.Password,
|
sshConfig.Host = hostModel.Name
|
||||||
Host: hostModel.Name,
|
sshConfig.Port = hostModel.Port
|
||||||
Port: hostModel.Port,
|
sshConfig.ExecTimeout = 5
|
||||||
ExecTimeout: 5,
|
sshConfig.AuthType = hostModel.AuthType
|
||||||
AuthType: hostModel.AuthType,
|
var password string
|
||||||
PrivateKey: hostModel.PrivateKey,
|
var privateKey string
|
||||||
|
if hostModel.AuthType == ssh.HostPassword {
|
||||||
|
password, err = hostModel.GetPasswordByHost(hostModel.Name)
|
||||||
|
if err != nil {
|
||||||
|
return json.CommonFailure(err.Error(), err)
|
||||||
|
}
|
||||||
|
sshConfig.Password = password
|
||||||
|
} else {
|
||||||
|
privateKey, err = hostModel.GetPrivateKeyByHost(hostModel.Name)
|
||||||
|
if err != nil {
|
||||||
|
return json.CommonFailure(err.Error(), err)
|
||||||
|
}
|
||||||
|
sshConfig.PrivateKey = privateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = ssh.Exec(sshConfig, "pwd")
|
_, err = ssh.Exec(sshConfig, "pwd")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return json.CommonFailure("连接失败-" + err.Error(), err)
|
return json.CommonFailure("连接失败-" + err.Error(), err)
|
||||||
|
@ -86,10 +99,8 @@ type HostForm struct {
|
||||||
Name string `binding:"Required;MaxSize(100)"`
|
Name string `binding:"Required;MaxSize(100)"`
|
||||||
Alias string `binding:"Required;MaxSize(32)"`
|
Alias string `binding:"Required;MaxSize(32)"`
|
||||||
Username string `binding:"Required;MaxSize(32)"`
|
Username string `binding:"Required;MaxSize(32)"`
|
||||||
Password string
|
|
||||||
Port int `binding:"Required;Range(1-65535)"`
|
Port int `binding:"Required;Range(1-65535)"`
|
||||||
AuthType ssh.HostAuthType `binding:"Required:Range(1,2)"`
|
AuthType ssh.HostAuthType `binding:"Required:Range(1,2)"`
|
||||||
PrivateKey string
|
|
||||||
Remark string
|
Remark string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,16 +119,9 @@ func Store(ctx *macaron.Context, form HostForm) string {
|
||||||
hostModel.Name = form.Name
|
hostModel.Name = form.Name
|
||||||
hostModel.Alias = form.Alias
|
hostModel.Alias = form.Alias
|
||||||
hostModel.Username = form.Username
|
hostModel.Username = form.Username
|
||||||
hostModel.Password = form.Password
|
|
||||||
hostModel.Port = form.Port
|
hostModel.Port = form.Port
|
||||||
hostModel.Remark = form.Remark
|
hostModel.Remark = form.Remark
|
||||||
hostModel.PrivateKey = form.PrivateKey
|
|
||||||
hostModel.AuthType = form.AuthType
|
hostModel.AuthType = form.AuthType
|
||||||
if hostModel.AuthType == ssh.HostPublicKey {
|
|
||||||
hostModel.Password = ""
|
|
||||||
} else {
|
|
||||||
hostModel.PrivateKey = ""
|
|
||||||
}
|
|
||||||
isCreate := false
|
isCreate := false
|
||||||
if id > 0 {
|
if id > 0 {
|
||||||
_, err = hostModel.UpdateBean(id)
|
_, err = hostModel.UpdateBean(id)
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/ouqiang/gocron/modules/logger"
|
"github.com/ouqiang/gocron/modules/logger"
|
||||||
"github.com/go-macaron/binding"
|
"github.com/go-macaron/binding"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/ouqiang/gocron/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 系统安装
|
// 系统安装
|
||||||
|
@ -60,7 +61,7 @@ func Store(ctx *macaron.Context, form InstallForm) string {
|
||||||
return json.CommonFailure("数据库配置写入文件失败", err)
|
return json.CommonFailure("数据库配置写入文件失败", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
app.InitDb()
|
models.Db = models.CreateDb()
|
||||||
// 创建数据库表
|
// 创建数据库表
|
||||||
migration := new(models.Migration)
|
migration := new(models.Migration)
|
||||||
err = migration.Exec(form.DbName)
|
err = migration.Exec(form.DbName)
|
||||||
|
@ -81,8 +82,9 @@ func Store(ctx *macaron.Context, form InstallForm) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
app.Installed = true
|
app.Installed = true
|
||||||
// 初始化定时任务等
|
// 初始化定时任务
|
||||||
app.InitResource()
|
serviceTask := new(service.Task)
|
||||||
|
serviceTask.Initialize()
|
||||||
|
|
||||||
return json.Success("安装成功", nil)
|
return json.Success("安装成功", nil)
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,15 +149,33 @@ func (h *HTTPHandler) Run(taskModel models.TaskHost) (result string, err error)
|
||||||
type SSHCommandHandler struct{}
|
type SSHCommandHandler struct{}
|
||||||
|
|
||||||
func (h *SSHCommandHandler) Run(taskModel models.TaskHost) (string, error) {
|
func (h *SSHCommandHandler) Run(taskModel models.TaskHost) (string, error) {
|
||||||
sshConfig := ssh.SSHConfig{
|
hostModel := new(models.Host)
|
||||||
User: taskModel.Username,
|
err := hostModel.Find(int(taskModel.HostId))
|
||||||
Password: taskModel.Password,
|
if err != nil {
|
||||||
Host: taskModel.Name,
|
return "", err
|
||||||
Port: taskModel.Port,
|
|
||||||
ExecTimeout: taskModel.Timeout,
|
|
||||||
AuthType: taskModel.AuthType,
|
|
||||||
PrivateKey: taskModel.PrivateKey,
|
|
||||||
}
|
}
|
||||||
|
sshConfig := ssh.SSHConfig{}
|
||||||
|
sshConfig.User = hostModel.Username
|
||||||
|
sshConfig.Host = hostModel.Name
|
||||||
|
sshConfig.Port = hostModel.Port
|
||||||
|
sshConfig.ExecTimeout = 5
|
||||||
|
sshConfig.AuthType = hostModel.AuthType
|
||||||
|
var password string
|
||||||
|
var privateKey string
|
||||||
|
if hostModel.AuthType == ssh.HostPassword {
|
||||||
|
password, err = hostModel.GetPasswordByHost(hostModel.Name)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
sshConfig.Password = password
|
||||||
|
} else {
|
||||||
|
privateKey, err = hostModel.GetPrivateKeyByHost(hostModel.Name)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
sshConfig.PrivateKey = privateKey
|
||||||
|
}
|
||||||
|
|
||||||
return ssh.Exec(sshConfig, taskModel.Command)
|
return ssh.Exec(sshConfig, taskModel.Command)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,8 +43,14 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="four fields">
|
<div class="fields">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
|
<div class="ui blue message">
|
||||||
|
密码认证: 把密码写入文件 gocron根目录/data/ssh/password/主机名<br>
|
||||||
|
例: echo '12345678' > data/ssh/password/127.0.0.1<br><br>
|
||||||
|
公钥认证: 把私钥写入文件 gocron根目录/data/ssh/private_key/主机名<br>
|
||||||
|
例: cp ~/.ssh/id_rsa data/ssh/private_key/127.0.0.1
|
||||||
|
</div>
|
||||||
<label>认证方式</label>
|
<label>认证方式</label>
|
||||||
<select name="auth_type" id="authType">
|
<select name="auth_type" id="authType">
|
||||||
<option value="2" {{{if .Host}}} {{{if eq .Host.AuthType 2}}}selected {{{end}}} {{{end}}} data-validate-type="selectPrivateKey" data-match="private_key">公钥</option>
|
<option value="2" {{{if .Host}}} {{{if eq .Host.AuthType 2}}}selected {{{end}}} {{{end}}} data-validate-type="selectPrivateKey" data-match="private_key">公钥</option>
|
||||||
|
@ -52,22 +58,6 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="two fields" id="private_key">
|
|
||||||
<div class="field">
|
|
||||||
<label>私钥 (~/.ssh/id_rsa)</label>
|
|
||||||
<div class="ui small input">
|
|
||||||
<textarea rows="7" name="private_key">{{{.Host.PrivateKey}}}</textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="four fields" id="password">
|
|
||||||
<div class="field">
|
|
||||||
<label>SSH密码</label>
|
|
||||||
<div class="ui small input">
|
|
||||||
<input type="text" placeholder="" name="password" value="{{{.Host.Password}}}">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="two fields">
|
<div class="two fields">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>备注</label>
|
<label>备注</label>
|
||||||
|
@ -85,28 +75,6 @@
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var $uiForm = $('.ui.form');
|
var $uiForm = $('.ui.form');
|
||||||
$(function() {
|
|
||||||
changeAuthType($('#authType').val());
|
|
||||||
});
|
|
||||||
|
|
||||||
function changeAuthType(type) {
|
|
||||||
// 私钥
|
|
||||||
if (type == 2) {
|
|
||||||
$('#password').hide();
|
|
||||||
$('#private_key').show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 密码
|
|
||||||
$('#private_key').hide();
|
|
||||||
$('#password').show();
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#authType').change(function() {
|
|
||||||
changeAuthType($(this).val());
|
|
||||||
});
|
|
||||||
registerSelectFormValidation("selectPrivateKey", $uiForm, $('#authType'), 'auth_type');
|
|
||||||
registerSelectFormValidation("selectPassword", $uiForm, $('#authType'), 'auth_type');
|
|
||||||
$($uiForm).form(
|
$($uiForm).form(
|
||||||
{
|
{
|
||||||
onSuccess: function(event, fields) {
|
onSuccess: function(event, fields) {
|
||||||
|
@ -152,24 +120,6 @@
|
||||||
prompt : '请输入有效的端口号'
|
prompt : '请输入有效的端口号'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
|
||||||
PrivateKey: {
|
|
||||||
identifier : 'private_key',
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
type : 'selectPrivateKey',
|
|
||||||
prompt : '请输入私钥'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
Password: {
|
|
||||||
identifier : 'password',
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
type : 'selectPassword',
|
|
||||||
prompt : '请输入密码'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
inline : true
|
inline : true
|
||||||
|
|
Loading…
Reference in New Issue