add ssh functions: Run Exec Output

This commit is contained in:
rinetd 2018-12-19 14:33:31 +08:00
parent 0e936a4f58
commit 08411d78e5
18 changed files with 634 additions and 13 deletions

View File

@ -18,6 +18,10 @@
## Example
### 在远程执行ssh命令
提供3个方法: Run() Exec() Output()
1. Run() : 程序执行后,不再受执行者控制. 适用于启动服务端进程.
2. Exec() : 在控制台同步实时输出程序的执行结果.
3. Output() : 会等待程序执行完成后,输出执行结果,在需要对执行的结果进行操作时使用.
```go
package main
import (
@ -32,7 +36,7 @@ func main() {
}
defer c.Close()
output, err := c.Exec("uptime")
output, err := c.Output("uptime")
if err != nil {
panic(err)
}

View File

@ -17,6 +17,7 @@ const DefaultTimeout = 30 * time.Second
type Client struct {
*Config
SSHClient *ssh.Client
SSHSession *ssh.Session
SFTPClient *sftp.Client
}
@ -65,7 +66,13 @@ func New(cnf *Config) (client *Client, err error) {
return client, errors.New("Failed to conn sftp: " + err.Error())
}
return &Client{SSHClient: sshClient, SFTPClient: sftpClient}, nil
session, err := sshClient.NewSession()
if err != nil {
return nil, err
}
// defer session.Close()
return &Client{SSHClient: sshClient, SFTPClient: sftpClient, SSHSession: session}, nil
}
// NewClient 根据配置
@ -149,4 +156,5 @@ func NewWithPrivateKey(Host, Port, User, Passphrase string) (client *Client, err
func (c *Client) Close() {
c.SFTPClient.Close()
c.SSHClient.Close()
c.SSHSession.Close()
}

124
example/bash/Makefile Normal file
View File

@ -0,0 +1,124 @@
PROJECT = transfer
VERSION = $(shell git describe)
BRANCH = $(shell git name-rev --name-only HEAD)
VERSION ="$(echo $TRAVIS_TAG)"
ARCNAME = $(PROJECT)-$(VERSION)-$(GOOS)-$(GOARCH)
ARTIFACTS_DIR=artifact
# ZIP="zip -9 -r"
# TAR="tar cvf"
# GZIP="gzip -9"
# GZIP_7Z="7za a -tgzip -mx9"
# ZIP_7Z="7za a -tzip -mx9"
ifndef ZIP
ifneq ($(shell which zip 2>/dev/null),)
ZIP := zip -9
endif
ifneq ($(shell which 7z 2>/dev/null),)
ZIP := 7z a -tzip -mx=9
endif
ifneq ($(shell which 7za 2>/dev/null),)
ZIP := 7za a -tzip -mx=9
endif
ifndef ZIP
$(warning "No zip / 7z / 7za in ($(PATH))")
ZIP := : zip_not_found
endif
endif
.PHONY: all release release-all
all: release-all
.PHONY: windows-dependencies
windows-dependencies:
@ go get github.com/josephspurrier/goversioninfo/cmd/goversioninfo
.PHONY: embed-assets
embed-assets:
@ GO111MODULE=off go get -u github.com/jteeuwen/go-bindata/...
@# go-bindata ./logos/microBadger_headert.png ./webpage.html
release:
env CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) go build $(FLAGS) -ldflags='-s -w -X github.com/rinetd/transfer/version.Version=$(VERSION)' -o build/$(GOOS)-$(GOARCH)/$(PROJECT)$(EXT)
- tar czf build/$(ARCNAME).tar.gz -C build/$(GOOS)-$(GOARCH)/ $(PROJECT)$(EXT)
- tar czf build/$(ARCNAME).tar.gz -C build/$(GOOS)-$(GOARCH)/ $(PROJECT)$(EXT)
ifeq ($(OS),Windows_NT)
cd dist; \
rm -f $(ARCNAME)-*-Win.zip; \
$(ZIP) $(ARCNAME)-$(VERSTR)-Win.zip build/$(GOOS)-$(GOARCH)/ $(PROJECT)$(EXT);
$(ZIP) dist/$(ARCNAME)-$(VERSTR)-Win.zip -r0 images/*.png;
endif
release-all:
# -@$(MAKE) release GOOS=darwin GOARCH=amd64
# -@$(MAKE) release GOOS=linux GOARCH=386
# -@$(MAKE) release GOOS=linux GOARCH=amd64
-@$(MAKE) release GOOS=windows GOARCH=386 EXT=.exe
# -@$(MAKE) release GOOS=windows GOARCH=amd64 EXT=.exe
.PHONY: windows
windows: windows-dependencies embed-assets
goversioninfo -icon=rc/icon.ico -manifest=rc/manifest.exe.manifest rc/versioninfo.json
@- rm binaries/*.exe
CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -x -ldflags="-s -w " -o binaries/deploy`date +%m%d`.exe
@# - rm binaries/deploy_windows_64bit.exe
@# - CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="-s -w -H=windowsgui -linkmode internal" -o binaries/deploy_windows_64bit.exe
rm resource.syso
platform:
# @$(MAKE) releaseGOOS=js GOARCH=wasm
# @$(MAKE) release GOOS=windows GOARCH=386 FLAGS='-ldflags="-H=windowsgui"' EXE=.exe
# @$(MAKE) release GOOS=windows GOARCH=amd64 FLAGS='-ldflags="-H=windowsgui"' EXE=.exe
# @$(MAKE) release GOOS=linux GOARCH=arm
# @$(MAKE) release GOOS=linux GOARCH=arm64
# @$(MAKE) release GOOS=linux GOARCH=mips
# @$(MAKE) release GOOS=linux GOARCH=mips64
# @$(MAKE) release GOOS=linux GOARCH=mips64le
# @$(MAKE) release GOOS=linux GOARCH=mipsle
# @$(MAKE) release GOOS=linux GOARCH=ppc64
# @$(MAKE) release GOOS=linux GOARCH=ppc64le
# @$(MAKE) release GOOS=linux GOARCH=s390x
# @$(MAKE) release GOOS=android GOARCH=386
# @$(MAKE) release GOOS=android GOARCH=amd64
# @$(MAKE) release GOOS=android GOARCH=arm
# @$(MAKE) release GOOS=android GOARCH=arm64
# @$(MAKE) release GOOS=darwin GOARCH=386
# @$(MAKE) release GOOS=darwin GOARCH=arm
# @$(MAKE) release GOOS=darwin GOARCH=arm64
# @$(MAKE) release GOOS=dragonfly GOARCH=amd64
# @$(MAKE) release GOOS=freebsd GOARCH=386
# @$(MAKE) release GOOS=freebsd GOARCH=amd64
# @$(MAKE) release GOOS=freebsd GOARCH=arm
# @$(MAKE) release GOOS=nacl GOARCH=386
# @$(MAKE) release GOOS=nacl GOARCH=amd64p32
# @$(MAKE) release GOOS=nacl GOARCH=arm
# @$(MAKE) release GOOS=netbsd GOARCH=386
# @$(MAKE) release GOOS=netbsd GOARCH=amd64
# @$(MAKE) release GOOS=netbsd GOARCH=arm
# @$(MAKE) release GOOS=openbsd GOARCH=386
# @$(MAKE) release GOOS=openbsd GOARCH=amd64
# @$(MAKE) release GOOS=openbsd GOARCH=arm
# @$(MAKE) release GOOS=plan9 GOARCH=386
# @$(MAKE) release GOOS=plan9 GOARCH=amd64
# @$(MAKE) release GOOS=plan9 GOARCH=arm
# @$(MAKE) release GOOS=solaris GOARCH=amd64
.PHONY: build
build:
go get ./...
.PHONY: test
test:
go get -t ./...
go test -v ...
build-image:
docker build -t rientd/transfer .
clean:
rm -rf build dist

52
example/getdata/Makefile Normal file
View File

@ -0,0 +1,52 @@
COMPILE_TIME = $(shell date +"%Y-%M-%d %H:%M:%S")
BUILD=`date +%FT%T%z`
# Setup the -ldflags option for go build here, interpolate the variable values
LDFLAGS_f1=-ldflags "-w -s -X main.Version=${VERSION} -X main.Build=${BUILD} -X main.Entry=f1"
LDFLAGS_f2=-ldflags "-w -s -X main.Version=${VERSION} -X main.Build=${BUILD} -X main.Entry=f2"
name:=getdata
# make ver=release
ifeq ($(ver), debug)
CXXFLAGS = -c -g -Ddebug
else
CXXFLAGS = -c -O3
endif
.PHONY: all
all: windows
.PHONY: windows-dependencies
windows-dependencies:
go get github.com/josephspurrier/goversioninfo/cmd/goversioninfo
.PHONY: embed-assets
embed-assets:
@# go get github.com/jteeuwen/go-bindata/...
@# go-bindata ./logos/$(name)_headert.png ./webpage.html
.PHONY: linux
linux: *.go embed-assets
GOOS=linux GOARCH=amd64 go build -o output/$(name)_linux_64bit
GOOS=linux GOARCH=386 go build -o output/$(name)_linux_32bit
strip output/$(name)_linux_*
.PHONY: windows
windows: *.go windows-dependencies embed-assets
goversioninfo -icon=rc/icon.ico -manifest=rc/manifest.exe.manifest rc/versioninfo.json
@- rm output/*.exe
CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags="-s -w " -o output/$(name)_`date +%m-%d`.exe
@# - rm output/$(name)_windows_64bit.exe
@# - CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="-s -w -H=windowsgui -linkmode internal" -o output/deploy_windows_64bit.exe
rm resource.syso
.PHONY: osx
osx: *.go embed-assets
GOOS=darwin GOARCH=amd64 go build -o output/$(name)_osx_64bit
GOOS=darwin GOARCH=386 go build -o output/$(name)_osx_32bit
.PHONY: clean
clean:
rm -rf output/*

105
example/getdata/main.go Normal file
View File

@ -0,0 +1,105 @@
package getdata
import (
"fmt"
"log"
"os"
"path"
"time"
"github.com/pkg/sftp"
"golang.org/x/crypto/ssh"
)
func connect(user, password, host string, port int) (*sftp.Client, error) {
var (
auth []ssh.AuthMethod
addr string
clientConfig *ssh.ClientConfig
sshClient *ssh.Client
sftpClient *sftp.Client
err error
)
// get auth method
auth = make([]ssh.AuthMethod, 0)
auth = append(auth, ssh.Password(password))
clientConfig = &ssh.ClientConfig{
User: user,
Auth: auth,
Timeout: 30 * time.Second,
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
// connet to ssh
addr = fmt.Sprintf("%s:%d", host, port)
if sshClient, err = ssh.Dial("tcp", addr, clientConfig); err != nil {
return nil, err
}
// create sftp client
if sftpClient, err = sftp.NewClient(sshClient); err != nil {
return nil, err
}
return sftpClient, nil
}
var FORMAT = "2006-01-02"
var (
err error
sftpClient *sftp.Client
)
var dbnames = []string{"tower", "mengyin", "pingyi", "shizhi", "tancheng", "yinan", "yishui", "feixian", "gaoxinqu", "hedong", "jingkaiqu", "junan", "luozhuang", "lanling", "lanshan", "lingang", "linshu"}
func main() {
// 这里换成实际的 SSH 连接的 用户名密码主机名或IPSSH端口
// sftpClient, err = connect("root", "sdlylshl871016", "111.235.181.127", 443)
sftpClient, err = connect("root", "HR2018!!", "15.14.12.150", 22)
if err != nil {
log.Println(err)
}
defer sftpClient.Close()
// 用来测试的远程文件路径 和 本地文件夹
// fmt.Println(shizhi)
// var localDir = "."
date_dir := "db_" + time.Now().Format(FORMAT)
os.Mkdir(date_dir, 0755)
var lzkpbi = "/docker/backup/" + time.Now().Format(FORMAT) + "_lzkp_bi_inner.zip"
Down(lzkpbi, date_dir)
for _, n := range dbnames {
p := "/docker/backup/" + time.Now().Format(FORMAT) + "_" + n + "_inner.zip"
// fmt.Println(p)
Down(p, date_dir)
}
// fmt.Scanln()
}
func Down(src, dst string) {
fmt.Println(src, "数据正在复制中,请耐心等待...")
srcFile, err := sftpClient.Open(src)
if err != nil {
log.Println(err)
return
}
defer srcFile.Close()
var localFileName = path.Base(src)
dstFile, err := os.Create(path.Join(dst, localFileName))
if err != nil {
log.Println(err)
return
}
defer dstFile.Close()
if _, err = srcFile.WriteTo(dstFile); err != nil {
log.Println(err)
return
}
fmt.Println(src, "数据复制完成!")
}

BIN
example/getdata/rc/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="Hardentools" type="win32"/>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<!-- <requestedExecutionLevel level="asInvoker" uiAccess="false" /> -->
<!-- <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> -->
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

View File

@ -0,0 +1,43 @@
{
"_FixedFileInfo": {
"FileVersion": {
"Major": 18,
"Minor": 7,
"Patch": 16,
"Build": 0
},
"ProductVersion": {
"Major": 2018,
"Minor": 7,
"Patch": 16,
"Build": 0
},
"FileFlagsMask": "3f",
"FileFlags ": "00",
"FileOS": "040004",
"FileType": "01",
"FileSubType": "00"
},
"StringFileInfo": {
"FileDescription": "履职考评系统升级",
"FileVersion": "2.1.0",
"ProductName": "履职考评系统",
"ProductVersion": "2018.7.1",
"LegalCopyright": "Copyright@pytool",
"OriginalFilename": "update.exe",
"Comments": " ",
"CompanyName": "Company",
"InternalName": "",
"LegalTrademarks": "",
"PrivateBuild": "",
"SpecialBuild": ""
},
"VarFileInfo": {
"Translation": {
"LangID": "0409",
"CharsetID": "04B0"
}
},
"IconPath": "deploy.ico",
"ManifestPath": ""
}

126
example/runetl/Makefile Normal file
View File

@ -0,0 +1,126 @@
PROJECT = 数据同步
VERSION = $(shell git describe)
BRANCH = $(shell git name-rev --name-only HEAD)
VERSION ="$(echo $TRAVIS_TAG)"
ARCNAME = $(PROJECT)-$(VERSION)-$(GOOS)-$(GOARCH)
ARTIFACTS_DIR=artifact
# ZIP="zip -9 -r"
# TAR="tar cvf"
# GZIP="gzip -9"
# GZIP_7Z="7za a -tgzip -mx9"
# ZIP_7Z="7za a -tzip -mx9"
ifndef ZIP
ifneq ($(shell which zip 2>/dev/null),)
ZIP := zip -9
endif
ifneq ($(shell which 7z 2>/dev/null),)
ZIP := 7z a -tzip -mx=9
endif
ifneq ($(shell which 7za 2>/dev/null),)
ZIP := 7za a -tzip -mx=9
endif
ifndef ZIP
$(warning "No zip / 7z / 7za in ($(PATH))")
ZIP := : zip_not_found
endif
endif
.PHONY: all release release-all
all: release-all
.PHONY: windows-dependencies
windows-dependencies:
@ go get github.com/josephspurrier/goversioninfo/cmd/goversioninfo
.PHONY: embed-assets
embed-assets:
@ GO111MODULE=off go get -u github.com/jteeuwen/go-bindata/...
@# go-bindata ./logos/microBadger_headert.png ./webpage.html
release:
goversioninfo -icon=rc/icon.ico -manifest=rc/manifest.exe.manifest rc/versioninfo.json
env CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) go build $(FLAGS) -ldflags='-s -w -X github.com/rinetd/transfer/version.Version=$(VERSION)' -o build/$(GOOS)-$(GOARCH)/$(PROJECT)$(EXT)
rm resource.syso
- tar czf build/$(ARCNAME).tar.gz -C build/$(GOOS)-$(GOARCH)/ $(PROJECT)$(EXT)
- tar czf build/$(ARCNAME).tar.gz -C build/$(GOOS)-$(GOARCH)/ $(PROJECT)$(EXT)
ifeq ($(OS),Windows_NT)
cd dist; \
rm -f $(ARCNAME)-*-Win.zip; \
$(ZIP) $(ARCNAME)-$(VERSTR)-Win.zip build/$(GOOS)-$(GOARCH)/ $(PROJECT)$(EXT);
$(ZIP) dist/$(ARCNAME)-$(VERSTR)-Win.zip -r0 images/*.png;
endif
release-all:
# -@$(MAKE) release GOOS=darwin GOARCH=amd64
# -@$(MAKE) release GOOS=linux GOARCH=386
# -@$(MAKE) release GOOS=linux GOARCH=amd64
-@$(MAKE) release GOOS=windows GOARCH=386 EXT=.exe
# -@$(MAKE) release GOOS=windows GOARCH=amd64 EXT=.exe
.PHONY: windows
windows: windows-dependencies embed-assets
goversioninfo -icon=rc/icon.ico -manifest=rc/manifest.exe.manifest rc/versioninfo.json
@- rm binaries/*.exe
CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -x -ldflags="-s -w " -o binaries/deploy`date +%m%d`.exe
@# - rm binaries/deploy_windows_64bit.exe
@# - CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="-s -w -H=windowsgui -linkmode internal" -o binaries/deploy_windows_64bit.exe
rm resource.syso
platform:
# @$(MAKE) releaseGOOS=js GOARCH=wasm
# @$(MAKE) release GOOS=windows GOARCH=386 FLAGS='-ldflags="-H=windowsgui"' EXE=.exe
# @$(MAKE) release GOOS=windows GOARCH=amd64 FLAGS='-ldflags="-H=windowsgui"' EXE=.exe
# @$(MAKE) release GOOS=linux GOARCH=arm
# @$(MAKE) release GOOS=linux GOARCH=arm64
# @$(MAKE) release GOOS=linux GOARCH=mips
# @$(MAKE) release GOOS=linux GOARCH=mips64
# @$(MAKE) release GOOS=linux GOARCH=mips64le
# @$(MAKE) release GOOS=linux GOARCH=mipsle
# @$(MAKE) release GOOS=linux GOARCH=ppc64
# @$(MAKE) release GOOS=linux GOARCH=ppc64le
# @$(MAKE) release GOOS=linux GOARCH=s390x
# @$(MAKE) release GOOS=android GOARCH=386
# @$(MAKE) release GOOS=android GOARCH=amd64
# @$(MAKE) release GOOS=android GOARCH=arm
# @$(MAKE) release GOOS=android GOARCH=arm64
# @$(MAKE) release GOOS=darwin GOARCH=386
# @$(MAKE) release GOOS=darwin GOARCH=arm
# @$(MAKE) release GOOS=darwin GOARCH=arm64
# @$(MAKE) release GOOS=dragonfly GOARCH=amd64
# @$(MAKE) release GOOS=freebsd GOARCH=386
# @$(MAKE) release GOOS=freebsd GOARCH=amd64
# @$(MAKE) release GOOS=freebsd GOARCH=arm
# @$(MAKE) release GOOS=nacl GOARCH=386
# @$(MAKE) release GOOS=nacl GOARCH=amd64p32
# @$(MAKE) release GOOS=nacl GOARCH=arm
# @$(MAKE) release GOOS=netbsd GOARCH=386
# @$(MAKE) release GOOS=netbsd GOARCH=amd64
# @$(MAKE) release GOOS=netbsd GOARCH=arm
# @$(MAKE) release GOOS=openbsd GOARCH=386
# @$(MAKE) release GOOS=openbsd GOARCH=amd64
# @$(MAKE) release GOOS=openbsd GOARCH=arm
# @$(MAKE) release GOOS=plan9 GOARCH=386
# @$(MAKE) release GOOS=plan9 GOARCH=amd64
# @$(MAKE) release GOOS=plan9 GOARCH=arm
# @$(MAKE) release GOOS=solaris GOARCH=amd64
.PHONY: build
build:
go get ./...
.PHONY: test
test:
go get -t ./...
go test -v ...
build-image:
docker build -t rientd/transfer .
clean:
rm -rf build dist

31
example/runetl/main.go Normal file
View File

@ -0,0 +1,31 @@
package main
import (
"fmt"
"github.com/pytool/ssh"
)
func main() {
config := ssh.Default.WithHost("192.168.5.157").WithPassword("HR2018!!")
// config.Host = "15.14.12.153"
client, err := ssh.New(config)
// client, err := ssh.NewClient("localhost", "22", "root", "ubuntu")
if err != nil {
// panic(err)
fmt.Println("连接失败,按Enter键退出!")
fmt.Scanln()
}
defer client.Close()
err = client.Exec("sh /root/shetl/etl.sh")
if err != nil {
fmt.Println(err)
// panic(err)
fmt.Println("执行失败,按Enter键退出!")
fmt.Scanln()
}
// fmt.Printf("Uptime: %s\n", output)
}

BIN
example/runetl/rc/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="Hardentools" type="win32"/>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<!-- <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> -->
<!-- <requestedExecutionLevel level="highestAvailable" uiAccess="false" /> -->
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

View File

@ -0,0 +1,37 @@
{
"FixedFileInfo": {
"FileVersion": {
"Major": 1,
"Minor": 2,
"Patch": 0,
"Build": 1
},
"FileFlagsMask": "3f",
"FileFlags ": "00",
"FileOS": "040004",
"FileType": "01",
"FileSubType": "00"
},
"StringFileInfo": {
"Comments": "执行etl",
"CompanyName": "pytool",
"FileVersion": "",
"FileDescription": "执行数据同步etl",
"ProductName": "履职考评数据同步",
"ProductVersion": "2018.12.11",
"LegalCopyright": "Copyright@pytool",
"OriginalFilename": "etl.exe",
"InternalName": "",
"LegalTrademarks": "",
"PrivateBuild": "",
"SpecialBuild": ""
},
"VarFileInfo": {
"Translation": {
"LangID": "0409",
"CharsetID": "04B0"
}
},
"IconPath": "icon.ico",
"ManifestPath": ""
}

View File

@ -61,13 +61,13 @@ func (c *Client) downloadFile(remoteFile, local string) error {
rsum := c.Md5File(remoteFile)
ioutil.WriteFile(localFile+".md5", []byte(rsum), 755)
if FileExist(localFile) {
// 1. 检测远程是否存在
if rsum != "" {
lsum, _ := Md5File(localFile)
if lsum == rsum {
log.Println("sftp: 文件与本地一致,跳过上传", localFile)
log.Println("sftp: 文件与本地一致,跳过下载", localFile)
return nil
}
log.Println("sftp: 正在下载 ", localFile)
}
}
}
@ -196,6 +196,7 @@ func (c *Client) UploadFile(localFile, remote string) error {
log.Println("sftp: 文件与本地一致,跳过上传!", localFile)
return nil
}
log.Println("sftp: 正在上传 ", localFile)
}
}
@ -437,7 +438,7 @@ func (c *Client) Md5File(path string) string {
if c.IsNotExist(path) {
return ""
}
b, err := c.Run("md5sum " + path)
b, err := c.Output("md5sum " + path)
if err != nil {
return ""
}

70
ssh.go
View File

@ -1,30 +1,84 @@
package ssh
import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"path/filepath"
)
// Run Execute cmd on the remote host and return stderr and stdout
func (c *Client) Run(cmd string) ([]byte, error) {
// Run Execute cmd on the remote host for daemon service
func (c *Client) Run(cmd string) {
session, err := c.SSHClient.NewSession()
if err != nil {
return nil, err
return
}
defer session.Close()
return session.CombinedOutput(cmd)
session.Start(cmd)
if err != nil {
fmt.Printf("exec command:%v error:%v\n", cmd, err)
}
fmt.Printf("Waiting for command:%v to finish...\n", cmd)
//阻塞等待fork出的子进程执行的结果和cmd.Start()配合使用[不等待回收资源会导致fork出执行shell命令的子进程变为僵尸进程]
err = session.Wait()
if err != nil {
fmt.Printf(":Command finished with error: %v\n", err)
}
return
}
//Exec Execute cmd on the remote host and return stderr and stdout
func (c *Client) Exec(cmd string) ([]byte, error) {
//Exec Execute cmd on the remote host and bind stderr and stdout
func (c *Client) Exec(cmd string) error {
session, err := c.SSHClient.NewSession()
if err != nil {
return err
}
defer session.Close()
// session.Run(cmd)
// return session.CombinedOutput(cmd)
stdout, err := session.StdoutPipe()
// stderr, err = session.StderrPipe()
if err != nil {
fmt.Println(err)
return err
}
var b bytes.Buffer
session.Stderr = &b
session.Start(cmd)
//创建一个流来读取管道内内容,这里逻辑是通过一行一行的读取的
reader := bufio.NewReader(stdout)
//实时循环读取输出流中的一行内容
for {
line, err2 := reader.ReadString('\n')
if err2 != nil || io.EOF == err2 {
break
}
print(line)
}
//阻塞直到该命令执行完成该命令必须是被Start方法开始执行的
session.Wait()
if b.Len() > 0 {
return errors.New(b.String())
}
return nil
}
// Output Execute cmd on the remote host and return stderr and stdout
func (c *Client) Output(cmd string) ([]byte, error) {
session, err := c.SSHClient.NewSession()
if err != nil {
return nil, err
}
defer session.Close()
return session.CombinedOutput(cmd)
// session.Run(cmd)
// return session.CombinedOutput(cmd)
return session.Output(cmd)
}
// RunScript Executes a shell script file on the remote machine.