mirror of
https://github.com/TeaOSLab/EdgeNode.git
synced 2025-11-03 23:20:25 +08:00
优化命令执行相关代码
This commit is contained in:
@@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeNode/internal/firewalls/nftables"
|
"github.com/TeaOSLab/EdgeNode/internal/firewalls/nftables"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
||||||
|
executils "github.com/TeaOSLab/EdgeNode/internal/utils/exec"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/zero"
|
"github.com/TeaOSLab/EdgeNode/internal/zero"
|
||||||
"github.com/iwind/TeaGo/lists"
|
"github.com/iwind/TeaGo/lists"
|
||||||
"github.com/iwind/TeaGo/types"
|
"github.com/iwind/TeaGo/types"
|
||||||
@@ -21,6 +22,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var SharedDDoSProtectionManager = NewDDoSProtectionManager()
|
var SharedDDoSProtectionManager = NewDDoSProtectionManager()
|
||||||
@@ -263,23 +265,21 @@ func (this *DDoSProtectionManager) addTCPRules(tcpConfig *ddosconfigs.TCPConfig)
|
|||||||
// 添加新规则
|
// 添加新规则
|
||||||
for _, port := range ports {
|
for _, port := range ports {
|
||||||
if maxConnections > 0 {
|
if maxConnections > 0 {
|
||||||
var cmd = exec.Command(this.nftPath, "add", "rule", protocol, filter.Name, nftablesChainName, "tcp", "dport", types.String(port), "ct", "count", "over", types.String(maxConnections), "counter", "drop", "comment", this.encodeUserData([]string{"tcp", types.String(port), "maxConnections", types.String(maxConnections)}))
|
var cmd = executils.NewTimeoutCmd(10*time.Second, this.nftPath, "add", "rule", protocol, filter.Name, nftablesChainName, "tcp", "dport", types.String(port), "ct", "count", "over", types.String(maxConnections), "counter", "drop", "comment", this.encodeUserData([]string{"tcp", types.String(port), "maxConnections", types.String(maxConnections)}))
|
||||||
var stderr = &bytes.Buffer{}
|
cmd.WithStderr()
|
||||||
cmd.Stderr = stderr
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("add nftables rule '" + cmd.String() + "' failed: " + err.Error() + " (" + stderr.String() + ")")
|
return errors.New("add nftables rule '" + cmd.String() + "' failed: " + err.Error() + " (" + cmd.Stderr() + ")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO 让用户选择是drop还是reject
|
// TODO 让用户选择是drop还是reject
|
||||||
if maxConnectionsPerIP > 0 {
|
if maxConnectionsPerIP > 0 {
|
||||||
var cmd = exec.Command(this.nftPath, "add", "rule", protocol, filter.Name, nftablesChainName, "tcp", "dport", types.String(port), "meter", "meter-"+protocol+"-"+types.String(port)+"-max-connections", "{ "+protocol+" saddr ct count over "+types.String(maxConnectionsPerIP)+" }", "counter", "drop", "comment", this.encodeUserData([]string{"tcp", types.String(port), "maxConnectionsPerIP", types.String(maxConnectionsPerIP)}))
|
var cmd = executils.NewTimeoutCmd(10*time.Second, this.nftPath, "add", "rule", protocol, filter.Name, nftablesChainName, "tcp", "dport", types.String(port), "meter", "meter-"+protocol+"-"+types.String(port)+"-max-connections", "{ "+protocol+" saddr ct count over "+types.String(maxConnectionsPerIP)+" }", "counter", "drop", "comment", this.encodeUserData([]string{"tcp", types.String(port), "maxConnectionsPerIP", types.String(maxConnectionsPerIP)}))
|
||||||
var stderr = &bytes.Buffer{}
|
cmd.WithStderr()
|
||||||
cmd.Stderr = stderr
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("add nftables rule '" + cmd.String() + "' failed: " + err.Error() + " (" + stderr.String() + ")")
|
return errors.New("add nftables rule '" + cmd.String() + "' failed: " + err.Error() + " (" + cmd.Stderr() + ")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,20 +287,18 @@ func (this *DDoSProtectionManager) addTCPRules(tcpConfig *ddosconfigs.TCPConfig)
|
|||||||
// TODO 让用户选择是drop还是reject
|
// TODO 让用户选择是drop还是reject
|
||||||
if newConnectionsMinutelyRate > 0 {
|
if newConnectionsMinutelyRate > 0 {
|
||||||
if newConnectionsMinutelyRateBlockTimeout > 0 {
|
if newConnectionsMinutelyRateBlockTimeout > 0 {
|
||||||
var cmd = exec.Command(this.nftPath, "add", "rule", protocol, filter.Name, nftablesChainName, "tcp", "dport", types.String(port), "ct", "state", "new", "meter", "meter-"+protocol+"-"+types.String(port)+"-new-connections-rate", "{ "+protocol+" saddr limit rate over "+types.String(newConnectionsMinutelyRate)+"/minute burst "+types.String(newConnectionsMinutelyRate+3)+" packets }", "add", "@deny_set", "{"+protocol+" saddr timeout "+types.String(newConnectionsMinutelyRateBlockTimeout)+"s}", "comment", this.encodeUserData([]string{"tcp", types.String(port), "newConnectionsRate", types.String(newConnectionsMinutelyRate), types.String(newConnectionsMinutelyRateBlockTimeout)}))
|
var cmd = executils.NewTimeoutCmd(10*time.Second, this.nftPath, "add", "rule", protocol, filter.Name, nftablesChainName, "tcp", "dport", types.String(port), "ct", "state", "new", "meter", "meter-"+protocol+"-"+types.String(port)+"-new-connections-rate", "{ "+protocol+" saddr limit rate over "+types.String(newConnectionsMinutelyRate)+"/minute burst "+types.String(newConnectionsMinutelyRate+3)+" packets }", "add", "@deny_set", "{"+protocol+" saddr timeout "+types.String(newConnectionsMinutelyRateBlockTimeout)+"s}", "comment", this.encodeUserData([]string{"tcp", types.String(port), "newConnectionsRate", types.String(newConnectionsMinutelyRate), types.String(newConnectionsMinutelyRateBlockTimeout)}))
|
||||||
var stderr = &bytes.Buffer{}
|
cmd.WithStderr()
|
||||||
cmd.Stderr = stderr
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("add nftables rule '" + cmd.String() + "' failed: " + err.Error() + " (" + stderr.String() + ")")
|
return errors.New("add nftables rule '" + cmd.String() + "' failed: " + err.Error() + " (" + cmd.Stderr() + ")")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var cmd = exec.Command(this.nftPath, "add", "rule", protocol, filter.Name, nftablesChainName, "tcp", "dport", types.String(port), "ct", "state", "new", "meter", "meter-"+protocol+"-"+types.String(port)+"-new-connections-rate", "{ "+protocol+" saddr limit rate over "+types.String(newConnectionsMinutelyRate)+"/minute burst "+types.String(newConnectionsMinutelyRate+3)+" packets }" /**"add", "@deny_set", "{"+protocol+" saddr}",**/, "counter", "drop", "comment", this.encodeUserData([]string{"tcp", types.String(port), "newConnectionsRate", "0"}))
|
var cmd = executils.NewTimeoutCmd(10*time.Second, this.nftPath, "add", "rule", protocol, filter.Name, nftablesChainName, "tcp", "dport", types.String(port), "ct", "state", "new", "meter", "meter-"+protocol+"-"+types.String(port)+"-new-connections-rate", "{ "+protocol+" saddr limit rate over "+types.String(newConnectionsMinutelyRate)+"/minute burst "+types.String(newConnectionsMinutelyRate+3)+" packets }" /**"add", "@deny_set", "{"+protocol+" saddr}",**/, "counter", "drop", "comment", this.encodeUserData([]string{"tcp", types.String(port), "newConnectionsRate", "0"}))
|
||||||
var stderr = &bytes.Buffer{}
|
cmd.WithStderr()
|
||||||
cmd.Stderr = stderr
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("add nftables rule '" + cmd.String() + "' failed: " + err.Error() + " (" + stderr.String() + ")")
|
return errors.New("add nftables rule '" + cmd.String() + "' failed: " + err.Error() + " (" + cmd.Stderr() + ")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -309,20 +307,18 @@ func (this *DDoSProtectionManager) addTCPRules(tcpConfig *ddosconfigs.TCPConfig)
|
|||||||
// TODO 让用户选择是drop还是reject
|
// TODO 让用户选择是drop还是reject
|
||||||
if newConnectionsSecondlyRate > 0 {
|
if newConnectionsSecondlyRate > 0 {
|
||||||
if newConnectionsSecondlyRateBlockTimeout > 0 {
|
if newConnectionsSecondlyRateBlockTimeout > 0 {
|
||||||
var cmd = exec.Command(this.nftPath, "add", "rule", protocol, filter.Name, nftablesChainName, "tcp", "dport", types.String(port), "ct", "state", "new", "meter", "meter-"+protocol+"-"+types.String(port)+"-new-connections-secondly-rate", "{ "+protocol+" saddr limit rate over "+types.String(newConnectionsSecondlyRate)+"/second burst "+types.String(newConnectionsSecondlyRate+3)+" packets }", "add", "@deny_set", "{"+protocol+" saddr timeout "+types.String(newConnectionsSecondlyRateBlockTimeout)+"s}", "comment", this.encodeUserData([]string{"tcp", types.String(port), "newConnectionsSecondlyRate", types.String(newConnectionsSecondlyRate), types.String(newConnectionsSecondlyRateBlockTimeout)}))
|
var cmd = executils.NewTimeoutCmd(10*time.Second, this.nftPath, "add", "rule", protocol, filter.Name, nftablesChainName, "tcp", "dport", types.String(port), "ct", "state", "new", "meter", "meter-"+protocol+"-"+types.String(port)+"-new-connections-secondly-rate", "{ "+protocol+" saddr limit rate over "+types.String(newConnectionsSecondlyRate)+"/second burst "+types.String(newConnectionsSecondlyRate+3)+" packets }", "add", "@deny_set", "{"+protocol+" saddr timeout "+types.String(newConnectionsSecondlyRateBlockTimeout)+"s}", "comment", this.encodeUserData([]string{"tcp", types.String(port), "newConnectionsSecondlyRate", types.String(newConnectionsSecondlyRate), types.String(newConnectionsSecondlyRateBlockTimeout)}))
|
||||||
var stderr = &bytes.Buffer{}
|
cmd.WithStderr()
|
||||||
cmd.Stderr = stderr
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("add nftables rule '" + cmd.String() + "' failed: " + err.Error() + " (" + stderr.String() + ")")
|
return errors.New("add nftables rule '" + cmd.String() + "' failed: " + err.Error() + " (" + cmd.Stderr() + ")")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var cmd = exec.Command(this.nftPath, "add", "rule", protocol, filter.Name, nftablesChainName, "tcp", "dport", types.String(port), "ct", "state", "new", "meter", "meter-"+protocol+"-"+types.String(port)+"-new-connections-secondly-rate", "{ "+protocol+" saddr limit rate over "+types.String(newConnectionsSecondlyRate)+"/second burst "+types.String(newConnectionsSecondlyRate+3)+" packets }" /**"add", "@deny_set", "{"+protocol+" saddr}",**/, "counter", "drop", "comment", this.encodeUserData([]string{"tcp", types.String(port), "newConnectionsSecondlyRate", "0"}))
|
var cmd = executils.NewTimeoutCmd(10*time.Second, this.nftPath, "add", "rule", protocol, filter.Name, nftablesChainName, "tcp", "dport", types.String(port), "ct", "state", "new", "meter", "meter-"+protocol+"-"+types.String(port)+"-new-connections-secondly-rate", "{ "+protocol+" saddr limit rate over "+types.String(newConnectionsSecondlyRate)+"/second burst "+types.String(newConnectionsSecondlyRate+3)+" packets }" /**"add", "@deny_set", "{"+protocol+" saddr}",**/, "counter", "drop", "comment", this.encodeUserData([]string{"tcp", types.String(port), "newConnectionsSecondlyRate", "0"}))
|
||||||
var stderr = &bytes.Buffer{}
|
cmd.WithStderr()
|
||||||
cmd.Stderr = stderr
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("add nftables rule '" + cmd.String() + "' failed: " + err.Error() + " (" + stderr.String() + ")")
|
return errors.New("add nftables rule '" + cmd.String() + "' failed: " + err.Error() + " (" + cmd.Stderr() + ")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,15 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeNode/internal/conns"
|
"github.com/TeaOSLab/EdgeNode/internal/conns"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
||||||
|
executils "github.com/TeaOSLab/EdgeNode/internal/utils/exec"
|
||||||
"github.com/iwind/TeaGo/types"
|
"github.com/iwind/TeaGo/types"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type firewalldCmd struct {
|
type firewalldCmd struct {
|
||||||
cmd *exec.Cmd
|
cmd *executils.Cmd
|
||||||
denyIP string
|
denyIP string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +34,7 @@ func NewFirewalld() *Firewalld {
|
|||||||
|
|
||||||
path, err := exec.LookPath("firewall-cmd")
|
path, err := exec.LookPath("firewall-cmd")
|
||||||
if err == nil && len(path) > 0 {
|
if err == nil && len(path) > 0 {
|
||||||
var cmd = exec.Command(path, "--state")
|
var cmd = executils.NewTimeoutCmd(3*time.Second, path, "--state")
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
firewalld.exe = path
|
firewalld.exe = path
|
||||||
@@ -85,7 +87,7 @@ func (this *Firewalld) AllowPort(port int, protocol string) error {
|
|||||||
if !this.isReady {
|
if !this.isReady {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var cmd = exec.Command(this.exe, "--add-port="+types.String(port)+"/"+protocol)
|
var cmd = executils.NewTimeoutCmd(10*time.Second, this.exe, "--add-port="+types.String(port)+"/"+protocol)
|
||||||
this.pushCmd(cmd, "")
|
this.pushCmd(cmd, "")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -95,12 +97,12 @@ func (this *Firewalld) AllowPortRangesPermanently(portRanges [][2]int, protocol
|
|||||||
var port = this.PortRangeString(portRange, protocol)
|
var port = this.PortRangeString(portRange, protocol)
|
||||||
|
|
||||||
{
|
{
|
||||||
var cmd = exec.Command(this.exe, "--add-port="+port, "--permanent")
|
var cmd = executils.NewTimeoutCmd(10*time.Second, this.exe, "--add-port="+port, "--permanent")
|
||||||
this.pushCmd(cmd, "")
|
this.pushCmd(cmd, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
var cmd = exec.Command(this.exe, "--add-port="+port)
|
var cmd = executils.NewTimeoutCmd(10*time.Second, this.exe, "--add-port="+port)
|
||||||
this.pushCmd(cmd, "")
|
this.pushCmd(cmd, "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,7 +114,7 @@ func (this *Firewalld) RemovePort(port int, protocol string) error {
|
|||||||
if !this.isReady {
|
if !this.isReady {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var cmd = exec.Command(this.exe, "--remove-port="+types.String(port)+"/"+protocol)
|
var cmd = executils.NewTimeoutCmd(10*time.Second, this.exe, "--remove-port="+types.String(port)+"/"+protocol)
|
||||||
this.pushCmd(cmd, "")
|
this.pushCmd(cmd, "")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -121,12 +123,12 @@ func (this *Firewalld) RemovePortRangePermanently(portRange [2]int, protocol str
|
|||||||
var port = this.PortRangeString(portRange, protocol)
|
var port = this.PortRangeString(portRange, protocol)
|
||||||
|
|
||||||
{
|
{
|
||||||
var cmd = exec.Command(this.exe, "--remove-port="+port, "--permanent")
|
var cmd = executils.NewTimeoutCmd(10*time.Second, this.exe, "--remove-port="+port, "--permanent")
|
||||||
this.pushCmd(cmd, "")
|
this.pushCmd(cmd, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
var cmd = exec.Command(this.exe, "--remove-port="+port)
|
var cmd = executils.NewTimeoutCmd(10*time.Second, this.exe, "--remove-port="+port)
|
||||||
this.pushCmd(cmd, "")
|
this.pushCmd(cmd, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +161,7 @@ func (this *Firewalld) RejectSourceIP(ip string, timeoutSeconds int) error {
|
|||||||
if timeoutSeconds > 0 {
|
if timeoutSeconds > 0 {
|
||||||
args = append(args, "--timeout="+types.String(timeoutSeconds)+"s")
|
args = append(args, "--timeout="+types.String(timeoutSeconds)+"s")
|
||||||
}
|
}
|
||||||
var cmd = exec.Command(this.exe, args...)
|
var cmd = executils.NewTimeoutCmd(10*time.Second, this.exe, args...)
|
||||||
this.pushCmd(cmd, ip)
|
this.pushCmd(cmd, ip)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -182,7 +184,7 @@ func (this *Firewalld) DropSourceIP(ip string, timeoutSeconds int, async bool) e
|
|||||||
if timeoutSeconds > 0 {
|
if timeoutSeconds > 0 {
|
||||||
args = append(args, "--timeout="+types.String(timeoutSeconds)+"s")
|
args = append(args, "--timeout="+types.String(timeoutSeconds)+"s")
|
||||||
}
|
}
|
||||||
var cmd = exec.Command(this.exe, args...)
|
var cmd = executils.NewTimeoutCmd(10*time.Second, this.exe, args...)
|
||||||
if async {
|
if async {
|
||||||
this.pushCmd(cmd, ip)
|
this.pushCmd(cmd, ip)
|
||||||
return nil
|
return nil
|
||||||
@@ -209,13 +211,13 @@ func (this *Firewalld) RemoveSourceIP(ip string) error {
|
|||||||
}
|
}
|
||||||
for _, action := range []string{"reject", "drop"} {
|
for _, action := range []string{"reject", "drop"} {
|
||||||
var args = []string{"--remove-rich-rule=rule family='" + family + "' source address='" + ip + "' " + action}
|
var args = []string{"--remove-rich-rule=rule family='" + family + "' source address='" + ip + "' " + action}
|
||||||
var cmd = exec.Command(this.exe, args...)
|
var cmd = executils.NewTimeoutCmd(10*time.Second, this.exe, args...)
|
||||||
this.pushCmd(cmd, "")
|
this.pushCmd(cmd, "")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *Firewalld) pushCmd(cmd *exec.Cmd, denyIP string) {
|
func (this *Firewalld) pushCmd(cmd *executils.Cmd, denyIP string) {
|
||||||
select {
|
select {
|
||||||
case this.cmdQueue <- &firewalldCmd{cmd: cmd, denyIP: denyIP}:
|
case this.cmdQueue <- &firewalldCmd{cmd: cmd, denyIP: denyIP}:
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
package firewalls
|
package firewalls
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/conns"
|
"github.com/TeaOSLab/EdgeNode/internal/conns"
|
||||||
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
|
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
|
||||||
@@ -13,6 +12,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeNode/internal/firewalls/nftables"
|
"github.com/TeaOSLab/EdgeNode/internal/firewalls/nftables"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
||||||
|
executils "github.com/TeaOSLab/EdgeNode/internal/utils/exec"
|
||||||
"github.com/iwind/TeaGo/types"
|
"github.com/iwind/TeaGo/types"
|
||||||
"net"
|
"net"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -432,15 +432,14 @@ func (this *NFTablesFirewall) RemoveSourceIP(ip string) error {
|
|||||||
|
|
||||||
// 读取版本号
|
// 读取版本号
|
||||||
func (this *NFTablesFirewall) readVersion(nftPath string) string {
|
func (this *NFTablesFirewall) readVersion(nftPath string) string {
|
||||||
var cmd = exec.Command(nftPath, "--version")
|
var cmd = executils.NewTimeoutCmd(10*time.Second, nftPath, "--version")
|
||||||
var output = &bytes.Buffer{}
|
cmd.WithStdout()
|
||||||
cmd.Stdout = output
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
var outputString = output.String()
|
var outputString = cmd.Stdout()
|
||||||
var versionMatches = regexp.MustCompile(`nftables v([\d.]+)`).FindStringSubmatch(outputString)
|
var versionMatches = regexp.MustCompile(`nftables v([\d.]+)`).FindStringSubmatch(outputString)
|
||||||
if len(versionMatches) <= 1 {
|
if len(versionMatches) <= 1 {
|
||||||
return ""
|
return ""
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package iplibrary
|
package iplibrary
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
|
executils "github.com/TeaOSLab/EdgeNode/internal/utils/exec"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
@@ -13,9 +13,9 @@ import (
|
|||||||
|
|
||||||
// FirewalldAction Firewalld动作管理
|
// FirewalldAction Firewalld动作管理
|
||||||
// 常用命令:
|
// 常用命令:
|
||||||
// - 查询列表: firewall-cmd --list-all
|
// - 查询列表: firewall-cmd --list-all
|
||||||
// - 添加IP:firewall-cmd --add-rich-rule="rule family='ipv4' source address='192.168.2.32' reject" --timeout=30s
|
// - 添加IP:firewall-cmd --add-rich-rule="rule family='ipv4' source address='192.168.2.32' reject" --timeout=30s
|
||||||
// - 删除IP:firewall-cmd --remove-rich-rule="rule family='ipv4' source address='192.168.2.32' reject" --timeout=30s
|
// - 删除IP:firewall-cmd --remove-rich-rule="rule family='ipv4' source address='192.168.2.32' reject" --timeout=30s
|
||||||
type FirewalldAction struct {
|
type FirewalldAction struct {
|
||||||
BaseAction
|
BaseAction
|
||||||
|
|
||||||
@@ -144,12 +144,11 @@ func (this *FirewalldAction) runActionSingleIP(action string, listType IPListTyp
|
|||||||
// MAC OS直接返回
|
// MAC OS直接返回
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
cmd := exec.Command(path, args...)
|
cmd := executils.NewTimeoutCmd(30*time.Second, path, args...)
|
||||||
stderr := bytes.NewBuffer([]byte{})
|
cmd.WithStderr()
|
||||||
cmd.Stderr = stderr
|
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New(err.Error() + ", output: " + string(stderr.Bytes()))
|
return errors.New(err.Error() + ", output: " + cmd.Stderr())
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package iplibrary
|
package iplibrary
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
|
executils "github.com/TeaOSLab/EdgeNode/internal/utils/exec"
|
||||||
"github.com/iwind/TeaGo/types"
|
"github.com/iwind/TeaGo/types"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -16,12 +16,12 @@ import (
|
|||||||
// IPSetAction IPSet动作
|
// IPSetAction IPSet动作
|
||||||
// 相关命令:
|
// 相关命令:
|
||||||
// - 利用Firewalld管理set:
|
// - 利用Firewalld管理set:
|
||||||
// - 添加:firewall-cmd --permanent --new-ipset=edge_ip_list --type=hash:ip --option="timeout=0"
|
// - 添加:firewall-cmd --permanent --new-ipset=edge_ip_list --type=hash:ip --option="timeout=0"
|
||||||
// - 删除:firewall-cmd --permanent --delete-ipset=edge_ip_list
|
// - 删除:firewall-cmd --permanent --delete-ipset=edge_ip_list
|
||||||
// - 重载:firewall-cmd --reload
|
// - 重载:firewall-cmd --reload
|
||||||
// - firewalld+ipset: firewall-cmd --permanent --add-rich-rule="rule source ipset='edge_ip_list' reject"
|
// - firewalld+ipset: firewall-cmd --permanent --add-rich-rule="rule source ipset='edge_ip_list' reject"
|
||||||
// - 利用IPTables管理set:
|
// - 利用IPTables管理set:
|
||||||
// - 添加:iptables -A INPUT -m set --match-set edge_ip_list src -j REJECT
|
// - 添加:iptables -A INPUT -m set --match-set edge_ip_list src -j REJECT
|
||||||
// - 添加Item:ipset add edge_ip_list 192.168.2.32 timeout 30
|
// - 添加Item:ipset add edge_ip_list 192.168.2.32 timeout 30
|
||||||
// - 删除Item: ipset del edge_ip_list 192.168.2.32
|
// - 删除Item: ipset del edge_ip_list 192.168.2.32
|
||||||
// - 创建set:ipset create edge_ip_list hash:ip timeout 0
|
// - 创建set:ipset create edge_ip_list hash:ip timeout 0
|
||||||
@@ -30,16 +30,13 @@ import (
|
|||||||
type IPSetAction struct {
|
type IPSetAction struct {
|
||||||
BaseAction
|
BaseAction
|
||||||
|
|
||||||
config *firewallconfigs.FirewallActionIPSetConfig
|
config *firewallconfigs.FirewallActionIPSetConfig
|
||||||
errorBuf *bytes.Buffer
|
|
||||||
|
|
||||||
ipsetNotfound bool
|
ipsetNotfound bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIPSetAction() *IPSetAction {
|
func NewIPSetAction() *IPSetAction {
|
||||||
return &IPSetAction{
|
return &IPSetAction{}
|
||||||
errorBuf: &bytes.Buffer{},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *IPSetAction) Init(config *firewallconfigs.FirewallActionConfig) error {
|
func (this *IPSetAction) Init(config *firewallconfigs.FirewallActionConfig) error {
|
||||||
@@ -68,14 +65,13 @@ func (this *IPSetAction) Init(config *firewallconfigs.FirewallActionConfig) erro
|
|||||||
if len(listName) == 0 {
|
if len(listName) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var cmd = exec.Command(path, "create", listName, "hash:ip", "timeout", "0", "maxelem", "1000000")
|
var cmd = executils.NewTimeoutCmd(30*time.Second, path, "create", listName, "hash:ip", "timeout", "0", "maxelem", "1000000")
|
||||||
var stderr = bytes.NewBuffer([]byte{})
|
cmd.WithStderr()
|
||||||
cmd.Stderr = stderr
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var output = stderr.Bytes()
|
var output = cmd.Stderr()
|
||||||
if !bytes.Contains(output, []byte("already exists")) {
|
if !strings.Contains(output, "already exists") {
|
||||||
return errors.New("create ipset '" + listName + "': " + err.Error() + ", output: " + string(output))
|
return errors.New("create ipset '" + listName + "': " + err.Error() + ", output: " + output)
|
||||||
} else {
|
} else {
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
@@ -87,14 +83,13 @@ func (this *IPSetAction) Init(config *firewallconfigs.FirewallActionConfig) erro
|
|||||||
if len(listName) == 0 {
|
if len(listName) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var cmd = exec.Command(path, "create", listName, "hash:ip", "family", "inet6", "timeout", "0", "maxelem", "1000000")
|
var cmd = executils.NewTimeoutCmd(30*time.Second, path, "create", listName, "hash:ip", "family", "inet6", "timeout", "0", "maxelem", "1000000")
|
||||||
var stderr = bytes.NewBuffer([]byte{})
|
cmd.WithStderr()
|
||||||
cmd.Stderr = stderr
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var output = stderr.Bytes()
|
var output = cmd.Stderr()
|
||||||
if !bytes.Contains(output, []byte("already exists")) {
|
if !strings.Contains(output, "already exists") {
|
||||||
return errors.New("create ipset '" + listName + "': " + err.Error() + ", output: " + string(output))
|
return errors.New("create ipset '" + listName + "': " + err.Error() + ", output: " + output)
|
||||||
} else {
|
} else {
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
@@ -114,16 +109,15 @@ func (this *IPSetAction) Init(config *firewallconfigs.FirewallActionConfig) erro
|
|||||||
if len(listName) == 0 {
|
if len(listName) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
cmd := exec.Command(path, "--permanent", "--new-ipset="+listName, "--type=hash:ip", "--option=timeout=0", "--option=maxelem=1000000")
|
var cmd = executils.NewTimeoutCmd(30*time.Second, path, "--permanent", "--new-ipset="+listName, "--type=hash:ip", "--option=timeout=0", "--option=maxelem=1000000")
|
||||||
stderr := bytes.NewBuffer([]byte{})
|
cmd.WithStderr()
|
||||||
cmd.Stderr = stderr
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
output := stderr.Bytes()
|
var output = cmd.Stderr()
|
||||||
if bytes.Contains(output, []byte("NAME_CONFLICT")) {
|
if strings.Contains(output, "NAME_CONFLICT") {
|
||||||
err = nil
|
err = nil
|
||||||
} else {
|
} else {
|
||||||
return errors.New("firewall-cmd add ipset '" + listName + "': " + err.Error() + ", output: " + string(output))
|
return errors.New("firewall-cmd add ipset '" + listName + "': " + err.Error() + ", output: " + output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,16 +127,15 @@ func (this *IPSetAction) Init(config *firewallconfigs.FirewallActionConfig) erro
|
|||||||
if len(listName) == 0 {
|
if len(listName) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
cmd := exec.Command(path, "--permanent", "--new-ipset="+listName, "--type=hash:ip", "--option=family=inet6", "--option=timeout=0", "--option=maxelem=1000000")
|
var cmd = executils.NewTimeoutCmd(30*time.Second, path, "--permanent", "--new-ipset="+listName, "--type=hash:ip", "--option=family=inet6", "--option=timeout=0", "--option=maxelem=1000000")
|
||||||
stderr := bytes.NewBuffer([]byte{})
|
cmd.WithStderr()
|
||||||
cmd.Stderr = stderr
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var output = stderr.Bytes()
|
var output = cmd.Stderr()
|
||||||
if bytes.Contains(output, []byte("NAME_CONFLICT")) {
|
if strings.Contains(output, "NAME_CONFLICT") {
|
||||||
err = nil
|
err = nil
|
||||||
} else {
|
} else {
|
||||||
return errors.New("firewall-cmd add ipset '" + listName + "': " + err.Error() + ", output: " + string(output))
|
return errors.New("firewall-cmd add ipset '" + listName + "': " + err.Error() + ", output: " + output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,13 +145,11 @@ func (this *IPSetAction) Init(config *firewallconfigs.FirewallActionConfig) erro
|
|||||||
if len(listName) == 0 {
|
if len(listName) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var cmd = exec.Command(path, "--permanent", "--add-rich-rule=rule source ipset='"+listName+"' accept")
|
var cmd = executils.NewTimeoutCmd(30*time.Second, path, "--permanent", "--add-rich-rule=rule source ipset='"+listName+"' accept")
|
||||||
var stderr = bytes.NewBuffer([]byte{})
|
cmd.WithStderr()
|
||||||
cmd.Stderr = stderr
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var output = stderr.Bytes()
|
return errors.New("firewall-cmd add rich rule '" + listName + "': " + err.Error() + ", output: " + cmd.Stderr())
|
||||||
return errors.New("firewall-cmd add rich rule '" + listName + "': " + err.Error() + ", output: " + string(output))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,25 +158,21 @@ func (this *IPSetAction) Init(config *firewallconfigs.FirewallActionConfig) erro
|
|||||||
if len(listName) == 0 {
|
if len(listName) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var cmd = exec.Command(path, "--permanent", "--add-rich-rule=rule source ipset='"+listName+"' reject")
|
var cmd = executils.NewTimeoutCmd(30*time.Second, path, "--permanent", "--add-rich-rule=rule source ipset='"+listName+"' reject")
|
||||||
var stderr = bytes.NewBuffer([]byte{})
|
cmd.WithStderr()
|
||||||
cmd.Stderr = stderr
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var output = stderr.Bytes()
|
return errors.New("firewall-cmd add rich rule '" + listName + "': " + err.Error() + ", output: " + cmd.Stderr())
|
||||||
return errors.New("firewall-cmd add rich rule '" + listName + "': " + err.Error() + ", output: " + string(output))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// reload
|
// reload
|
||||||
{
|
{
|
||||||
cmd := exec.Command(path, "--reload")
|
var cmd = executils.NewTimeoutCmd(30*time.Second, path, "--reload")
|
||||||
stderr := bytes.NewBuffer([]byte{})
|
cmd.WithStderr()
|
||||||
cmd.Stderr = stderr
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var output = stderr.Bytes()
|
return errors.New("firewall-cmd reload: " + err.Error() + ", output: " + cmd.Stderr())
|
||||||
return errors.New("firewall-cmd reload: " + err.Error() + ", output: " + string(output))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,19 +191,17 @@ func (this *IPSetAction) Init(config *firewallconfigs.FirewallActionConfig) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检查规则是否存在
|
// 检查规则是否存在
|
||||||
var cmd = exec.Command(path, "-C", "INPUT", "-m", "set", "--match-set", listName, "src", "-j", "ACCEPT")
|
var cmd = executils.NewTimeoutCmd(30*time.Second, path, "-C", "INPUT", "-m", "set", "--match-set", listName, "src", "-j", "ACCEPT")
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
var exists = err == nil
|
var exists = err == nil
|
||||||
|
|
||||||
// 添加规则
|
// 添加规则
|
||||||
if !exists {
|
if !exists {
|
||||||
var cmd = exec.Command(path, "-A", "INPUT", "-m", "set", "--match-set", listName, "src", "-j", "ACCEPT")
|
var cmd = executils.NewTimeoutCmd(30*time.Second, path, "-A", "INPUT", "-m", "set", "--match-set", listName, "src", "-j", "ACCEPT")
|
||||||
var stderr = bytes.NewBuffer([]byte{})
|
cmd.WithStderr()
|
||||||
cmd.Stderr = stderr
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var output = stderr.Bytes()
|
return errors.New("iptables add rule: " + err.Error() + ", output: " + cmd.Stderr())
|
||||||
return errors.New("iptables add rule: " + err.Error() + ", output: " + string(output))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -228,18 +213,16 @@ func (this *IPSetAction) Init(config *firewallconfigs.FirewallActionConfig) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检查规则是否存在
|
// 检查规则是否存在
|
||||||
var cmd = exec.Command(path, "-C", "INPUT", "-m", "set", "--match-set", listName, "src", "-j", "REJECT")
|
var cmd = executils.NewTimeoutCmd(30*time.Second, path, "-C", "INPUT", "-m", "set", "--match-set", listName, "src", "-j", "REJECT")
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
var exists = err == nil
|
var exists = err == nil
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
var cmd = exec.Command(path, "-A", "INPUT", "-m", "set", "--match-set", listName, "src", "-j", "REJECT")
|
var cmd = executils.NewTimeoutCmd(30*time.Second, path, "-A", "INPUT", "-m", "set", "--match-set", listName, "src", "-j", "REJECT")
|
||||||
var stderr = bytes.NewBuffer([]byte{})
|
cmd.WithStderr()
|
||||||
cmd.Stderr = stderr
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var output = stderr.Bytes()
|
return errors.New("iptables add rule: " + err.Error() + ", output: " + cmd.Stderr())
|
||||||
return errors.New("iptables add rule: " + err.Error() + ", output: " + string(output))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -361,12 +344,11 @@ func (this *IPSetAction) runActionSingleIP(action string, listType IPListType, i
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
this.errorBuf.Reset()
|
var cmd = executils.NewTimeoutCmd(30*time.Second, path, args...)
|
||||||
var cmd = exec.Command(path, args...)
|
cmd.WithStderr()
|
||||||
cmd.Stderr = this.errorBuf
|
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var errString = this.errorBuf.String()
|
var errString = cmd.Stderr()
|
||||||
if action == "deleteItem" && strings.Contains(errString, "not added") {
|
if action == "deleteItem" && strings.Contains(errString, "not added") {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,23 @@
|
|||||||
package iplibrary
|
package iplibrary
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
|
executils "github.com/TeaOSLab/EdgeNode/internal/utils/exec"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IPTablesAction IPTables动作
|
// IPTablesAction IPTables动作
|
||||||
// 相关命令:
|
// 相关命令:
|
||||||
// iptables -A INPUT -s "192.168.2.32" -j ACCEPT
|
//
|
||||||
// iptables -A INPUT -s "192.168.2.32" -j REJECT
|
// iptables -A INPUT -s "192.168.2.32" -j ACCEPT
|
||||||
// iptables -D INPUT ...
|
// iptables -A INPUT -s "192.168.2.32" -j REJECT
|
||||||
// iptables -F INPUT
|
// iptables -D INPUT ...
|
||||||
|
// iptables -F INPUT
|
||||||
type IPTablesAction struct {
|
type IPTablesAction struct {
|
||||||
BaseAction
|
BaseAction
|
||||||
|
|
||||||
@@ -110,16 +113,15 @@ func (this *IPTablesAction) runActionSingleIP(action string, listType IPListType
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.Command(path, args...)
|
var cmd = executils.NewTimeoutCmd(30*time.Second, path, args...)
|
||||||
stderr := bytes.NewBuffer([]byte{})
|
cmd.WithStderr()
|
||||||
cmd.Stderr = stderr
|
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
output := stderr.Bytes()
|
var output = cmd.Stderr()
|
||||||
if bytes.Contains(output, []byte("No chain/target/match")) {
|
if strings.Contains(output, "No chain/target/match") {
|
||||||
err = nil
|
err = nil
|
||||||
} else {
|
} else {
|
||||||
return errors.New(err.Error() + ", output: " + string(output))
|
return errors.New(err.Error() + ", output: " + output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package iplibrary
|
package iplibrary
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
"os/exec"
|
executils "github.com/TeaOSLab/EdgeNode/internal/utils/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ScriptAction 脚本命令动作
|
// ScriptAction 脚本命令动作
|
||||||
@@ -45,25 +45,24 @@ func (this *ScriptAction) DeleteItem(listType IPListType, item *pb.IPItem) error
|
|||||||
|
|
||||||
func (this *ScriptAction) runAction(action string, listType IPListType, item *pb.IPItem) error {
|
func (this *ScriptAction) runAction(action string, listType IPListType, item *pb.IPItem) error {
|
||||||
// TODO 智能支持 .sh 脚本文件
|
// TODO 智能支持 .sh 脚本文件
|
||||||
cmd := exec.Command(this.config.Path)
|
var cmd = executils.NewTimeoutCmd(30*time.Second, this.config.Path)
|
||||||
cmd.Env = []string{
|
cmd.WithEnv([]string{
|
||||||
"ACTION=" + action,
|
"ACTION=" + action,
|
||||||
"TYPE=" + item.Type,
|
"TYPE=" + item.Type,
|
||||||
"IP_FROM=" + item.IpFrom,
|
"IP_FROM=" + item.IpFrom,
|
||||||
"IP_TO=" + item.IpTo,
|
"IP_TO=" + item.IpTo,
|
||||||
"EXPIRED_AT=" + fmt.Sprintf("%d", item.ExpiredAt),
|
"EXPIRED_AT=" + fmt.Sprintf("%d", item.ExpiredAt),
|
||||||
"LIST_TYPE=" + listType,
|
"LIST_TYPE=" + listType,
|
||||||
}
|
})
|
||||||
if len(this.config.Cwd) > 0 {
|
if len(this.config.Cwd) > 0 {
|
||||||
cmd.Dir = this.config.Cwd
|
cmd.WithDir(this.config.Cwd)
|
||||||
} else {
|
} else {
|
||||||
cmd.Dir = filepath.Dir(this.config.Path)
|
cmd.WithDir(filepath.Dir(this.config.Path))
|
||||||
}
|
}
|
||||||
stderr := bytes.NewBuffer([]byte{})
|
cmd.WithStderr()
|
||||||
cmd.Stderr = stderr
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New(err.Error() + ", output: " + string(stderr.Bytes()))
|
return errors.New(err.Error() + ", output: " + cmd.Stderr())
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package nodes
|
package nodes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -17,7 +16,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/rpc"
|
"github.com/TeaOSLab/EdgeNode/internal/rpc"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
executils "github.com/TeaOSLab/EdgeNode/internal/utils/exec"
|
||||||
"github.com/iwind/TeaGo/Tea"
|
"github.com/iwind/TeaGo/Tea"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -347,15 +346,15 @@ func (this *APIStream) handleCheckSystemdService(message *pb.NodeStreamMessage)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var cmd = utils.NewCommandExecutor()
|
var shortName = teaconst.SystemdServiceName
|
||||||
shortName := teaconst.SystemdServiceName
|
var cmd = executils.NewTimeoutCmd(10*time.Second, systemctl, "is-enabled", shortName)
|
||||||
cmd.Add(systemctl, "is-enabled", shortName)
|
cmd.WithStdout()
|
||||||
output, err := cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.replyFail(message.RequestId, "'systemctl' command error: "+err.Error())
|
this.replyFail(message.RequestId, "'systemctl' command error: "+err.Error())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if output == "enabled" {
|
if cmd.Stdout() == "enabled" {
|
||||||
this.replyOk(message.RequestId, "ok")
|
this.replyOk(message.RequestId, "ok")
|
||||||
} else {
|
} else {
|
||||||
this.replyFail(message.RequestId, "not installed")
|
this.replyFail(message.RequestId, "not installed")
|
||||||
@@ -385,16 +384,15 @@ func (this *APIStream) handleCheckLocalFirewall(message *pb.NodeStreamMessage) e
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var cmd = exec.Command(nft, "--version")
|
var cmd = executils.NewTimeoutCmd(10*time.Second, nft, "--version")
|
||||||
var output = &bytes.Buffer{}
|
cmd.WithStdout()
|
||||||
cmd.Stdout = output
|
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.replyFail(message.RequestId, "get version failed: "+err.Error())
|
this.replyFail(message.RequestId, "get version failed: "+err.Error())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var outputString = output.String()
|
var outputString = cmd.Stdout()
|
||||||
var versionMatches = regexp.MustCompile(`nftables v([\d.]+)`).FindStringSubmatch(outputString)
|
var versionMatches = regexp.MustCompile(`nftables v([\d.]+)`).FindStringSubmatch(outputString)
|
||||||
if len(versionMatches) <= 1 {
|
if len(versionMatches) <= 1 {
|
||||||
this.replyFail(message.RequestId, "can not get nft version")
|
this.replyFail(message.RequestId, "can not get nft version")
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package nodes
|
package nodes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
@@ -9,6 +8,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
||||||
|
executils "github.com/TeaOSLab/EdgeNode/internal/utils/exec"
|
||||||
"github.com/iwind/TeaGo/Tea"
|
"github.com/iwind/TeaGo/Tea"
|
||||||
"github.com/iwind/TeaGo/lists"
|
"github.com/iwind/TeaGo/lists"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
@@ -213,15 +213,14 @@ func (this *ListenerManager) findProcessNameWithPort(isUdp bool, port string) st
|
|||||||
option = "u"
|
option = "u"
|
||||||
}
|
}
|
||||||
|
|
||||||
var cmd = exec.Command(path, "-"+option+"lpn", "sport = :"+port)
|
var cmd = executils.NewTimeoutCmd(10*time.Second, path, "-"+option+"lpn", "sport = :"+port)
|
||||||
var output = &bytes.Buffer{}
|
cmd.WithStdout()
|
||||||
cmd.Stdout = output
|
|
||||||
err = cmd.Run()
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
var matches = regexp.MustCompile(`(?U)\(\("(.+)",pid=\d+,fd=\d+\)\)`).FindStringSubmatch(output.String())
|
var matches = regexp.MustCompile(`(?U)\(\("(.+)",pid=\d+,fd=\d+\)\)`).FindStringSubmatch(cmd.Stdout())
|
||||||
if len(matches) > 1 {
|
if len(matches) > 1 {
|
||||||
return matches[1]
|
return matches[1]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
||||||
|
executils "github.com/TeaOSLab/EdgeNode/internal/utils/exec"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -84,10 +85,10 @@ func (this *SystemServiceManager) setupSystemd(params maps.Map) error {
|
|||||||
if len(systemctl) == 0 {
|
if len(systemctl) == 0 {
|
||||||
return errors.New("can not find 'systemctl' on the system")
|
return errors.New("can not find 'systemctl' on the system")
|
||||||
}
|
}
|
||||||
cmd := utils.NewCommandExecutor()
|
|
||||||
shortName := teaconst.SystemdServiceName
|
shortName := teaconst.SystemdServiceName
|
||||||
cmd.Add(systemctl, "is-enabled", shortName)
|
var cmd = executils.NewTimeoutCmd(10*time.Second, systemctl, "is-enabled", shortName)
|
||||||
output, err := cmd.Run()
|
cmd.WithStdout()
|
||||||
|
err = cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -100,10 +101,10 @@ func (this *SystemServiceManager) setupSystemd(params maps.Map) error {
|
|||||||
// 启动Service
|
// 启动Service
|
||||||
goman.New(func() {
|
goman.New(func() {
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
_ = exec.Command(systemctl, "start", teaconst.SystemdServiceName).Start()
|
_ = executils.NewTimeoutCmd(30*time.Second, systemctl, "start", teaconst.SystemdServiceName).Start()
|
||||||
})
|
})
|
||||||
|
|
||||||
if output == "enabled" {
|
if cmd.Stdout() == "enabled" {
|
||||||
// 检查文件路径是否变化
|
// 检查文件路径是否变化
|
||||||
data, err := os.ReadFile("/etc/systemd/system/" + teaconst.SystemdServiceName + ".service")
|
data, err := os.ReadFile("/etc/systemd/system/" + teaconst.SystemdServiceName + ".service")
|
||||||
if err == nil && bytes.Index(data, []byte(exe)) > 0 {
|
if err == nil && bytes.Index(data, []byte(exe)) > 0 {
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
package nodes
|
package nodes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/events"
|
"github.com/TeaOSLab/EdgeNode/internal/events"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
||||||
|
executils "github.com/TeaOSLab/EdgeNode/internal/utils/exec"
|
||||||
"github.com/iwind/TeaGo/Tea"
|
"github.com/iwind/TeaGo/Tea"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -61,12 +62,16 @@ func (this *TOAManager) Run(config *nodeconfigs.TOAConfig) error {
|
|||||||
}
|
}
|
||||||
remotelogs.Println("TOA", "starting ...")
|
remotelogs.Println("TOA", "starting ...")
|
||||||
remotelogs.Println("TOA", "args: "+strings.Join(config.AsArgs(), " "))
|
remotelogs.Println("TOA", "args: "+strings.Join(config.AsArgs(), " "))
|
||||||
cmd := exec.Command(binPath, config.AsArgs()...)
|
cmd := executils.NewCmd(binPath, config.AsArgs()...)
|
||||||
err = cmd.Start()
|
err = cmd.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
this.pid = cmd.Process.Pid
|
var process = cmd.Process()
|
||||||
|
if process == nil {
|
||||||
|
return errors.New("start failed")
|
||||||
|
}
|
||||||
|
this.pid = process.Pid
|
||||||
|
|
||||||
goman.New(func() {
|
goman.New(func() {
|
||||||
_ = cmd.Wait()
|
_ = cmd.Wait()
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/rpc"
|
"github.com/TeaOSLab/EdgeNode/internal/rpc"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
||||||
|
executils "github.com/TeaOSLab/EdgeNode/internal/utils/exec"
|
||||||
"github.com/iwind/TeaGo/Tea"
|
"github.com/iwind/TeaGo/Tea"
|
||||||
stringutil "github.com/iwind/TeaGo/utils/string"
|
stringutil "github.com/iwind/TeaGo/utils/string"
|
||||||
"github.com/iwind/gosock/pkg/gosock"
|
"github.com/iwind/gosock/pkg/gosock"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
@@ -252,7 +252,7 @@ func (this *UpgradeManager) restart() error {
|
|||||||
// 启动
|
// 启动
|
||||||
exe = filepath.Dir(exe) + "/" + teaconst.ProcessName
|
exe = filepath.Dir(exe) + "/" + teaconst.ProcessName
|
||||||
|
|
||||||
var cmd = exec.Command(exe, "start")
|
var cmd = executils.NewCmd(exe, "start")
|
||||||
err = cmd.Start()
|
err = cmd.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
package clock
|
package clock
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
||||||
|
executils "github.com/TeaOSLab/EdgeNode/internal/utils/exec"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
@@ -46,12 +46,11 @@ func Sync() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func syncNtpdate(ntpdate string) error {
|
func syncNtpdate(ntpdate string) error {
|
||||||
var cmd = exec.Command(ntpdate, "pool.ntp.org")
|
var cmd = executils.NewTimeoutCmd(30*time.Second, ntpdate, "pool.ntp.org")
|
||||||
var stderr = &bytes.Buffer{}
|
cmd.WithStderr()
|
||||||
cmd.Stderr = stderr
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New(err.Error() + ": " + stderr.String())
|
return errors.New(err.Error() + ": " + cmd.Stderr())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
package utils
|
|
||||||
|
|
||||||
// 命令定义
|
|
||||||
type Command struct {
|
|
||||||
Name string
|
|
||||||
Args []string
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
package utils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"os/exec"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 命令执行器
|
|
||||||
type CommandExecutor struct {
|
|
||||||
commands []*Command
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取新对象
|
|
||||||
func NewCommandExecutor() *CommandExecutor {
|
|
||||||
return &CommandExecutor{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加命令
|
|
||||||
func (this *CommandExecutor) Add(command string, arg ...string) {
|
|
||||||
this.commands = append(this.commands, &Command{
|
|
||||||
Name: command,
|
|
||||||
Args: arg,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 执行命令
|
|
||||||
func (this *CommandExecutor) Run() (output string, err error) {
|
|
||||||
if len(this.commands) == 0 {
|
|
||||||
return "", errors.New("no commands no run")
|
|
||||||
}
|
|
||||||
var lastCmd *exec.Cmd = nil
|
|
||||||
var lastData []byte = nil
|
|
||||||
for _, command := range this.commands {
|
|
||||||
cmd := exec.Command(command.Name, command.Args...)
|
|
||||||
stdout := bytes.NewBuffer([]byte{})
|
|
||||||
cmd.Stdout = stdout
|
|
||||||
if lastCmd != nil {
|
|
||||||
cmd.Stdin = bytes.NewBuffer(lastData)
|
|
||||||
}
|
|
||||||
err = cmd.Start()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = cmd.Wait()
|
|
||||||
if err != nil {
|
|
||||||
_, ok := err.(*exec.ExitError)
|
|
||||||
if ok {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
lastData = stdout.Bytes()
|
|
||||||
|
|
||||||
lastCmd = cmd
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(bytes.TrimSpace(lastData)), nil
|
|
||||||
}
|
|
||||||
162
internal/utils/exec/cmd.go
Normal file
162
internal/utils/exec/cmd.go
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package executils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Cmd struct {
|
||||||
|
name string
|
||||||
|
args []string
|
||||||
|
env []string
|
||||||
|
dir string
|
||||||
|
|
||||||
|
ctx context.Context
|
||||||
|
timeout time.Duration
|
||||||
|
cancelFunc func()
|
||||||
|
|
||||||
|
captureStdout bool
|
||||||
|
captureStderr bool
|
||||||
|
|
||||||
|
stdout *bytes.Buffer
|
||||||
|
stderr *bytes.Buffer
|
||||||
|
|
||||||
|
rawCmd *exec.Cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCmd(name string, args ...string) *Cmd {
|
||||||
|
return &Cmd{
|
||||||
|
name: name,
|
||||||
|
args: args,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTimeoutCmd(timeout time.Duration, name string, args ...string) *Cmd {
|
||||||
|
return (&Cmd{
|
||||||
|
name: name,
|
||||||
|
args: args,
|
||||||
|
}).WithTimeout(timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Cmd) WithTimeout(timeout time.Duration) *Cmd {
|
||||||
|
this.timeout = timeout
|
||||||
|
|
||||||
|
ctx, cancelFunc := context.WithTimeout(context.Background(), timeout)
|
||||||
|
this.ctx = ctx
|
||||||
|
this.cancelFunc = cancelFunc
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Cmd) WithStdout() *Cmd {
|
||||||
|
this.captureStdout = true
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Cmd) WithStderr() *Cmd {
|
||||||
|
this.captureStderr = true
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Cmd) WithEnv(env []string) *Cmd {
|
||||||
|
this.env = env
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Cmd) WithDir(dir string) *Cmd {
|
||||||
|
this.dir = dir
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Cmd) Start() error {
|
||||||
|
var cmd = this.compose()
|
||||||
|
return cmd.Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Cmd) Wait() error {
|
||||||
|
var cmd = this.compose()
|
||||||
|
return cmd.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Cmd) Run() error {
|
||||||
|
if this.cancelFunc != nil {
|
||||||
|
defer this.cancelFunc()
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmd = this.compose()
|
||||||
|
return cmd.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Cmd) RawStdout() string {
|
||||||
|
if this.stdout != nil {
|
||||||
|
return this.stdout.String()
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Cmd) Stdout() string {
|
||||||
|
return strings.TrimSpace(this.RawStdout())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Cmd) RawStderr() string {
|
||||||
|
if this.stderr != nil {
|
||||||
|
return this.stderr.String()
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Cmd) Stderr() string {
|
||||||
|
return strings.TrimSpace(this.RawStderr())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Cmd) String() string {
|
||||||
|
if this.rawCmd != nil {
|
||||||
|
return this.rawCmd.String()
|
||||||
|
}
|
||||||
|
var newCmd = exec.Command(this.name, this.args...)
|
||||||
|
return newCmd.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Cmd) Process() *os.Process {
|
||||||
|
if this.rawCmd != nil {
|
||||||
|
return this.rawCmd.Process
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Cmd) compose() *exec.Cmd {
|
||||||
|
if this.rawCmd != nil {
|
||||||
|
return this.rawCmd
|
||||||
|
}
|
||||||
|
|
||||||
|
if this.ctx != nil {
|
||||||
|
this.rawCmd = exec.CommandContext(this.ctx, this.name, this.args...)
|
||||||
|
} else {
|
||||||
|
this.rawCmd = exec.Command(this.name, this.args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if this.env != nil {
|
||||||
|
this.rawCmd.Env = this.env
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(this.dir) > 0 {
|
||||||
|
this.rawCmd.Dir = this.dir
|
||||||
|
}
|
||||||
|
|
||||||
|
if this.captureStdout {
|
||||||
|
this.stdout = &bytes.Buffer{}
|
||||||
|
this.rawCmd.Stdout = this.stdout
|
||||||
|
}
|
||||||
|
if this.captureStderr {
|
||||||
|
this.stderr = &bytes.Buffer{}
|
||||||
|
this.rawCmd.Stderr = this.stderr
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.rawCmd
|
||||||
|
}
|
||||||
61
internal/utils/exec/cmd_test.go
Normal file
61
internal/utils/exec/cmd_test.go
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package executils_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
executils "github.com/TeaOSLab/EdgeNode/internal/utils/exec"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewTimeoutCmd_Sleep(t *testing.T) {
|
||||||
|
var cmd = executils.NewTimeoutCmd(1*time.Second, "sleep", "3")
|
||||||
|
cmd.WithStdout()
|
||||||
|
cmd.WithStderr()
|
||||||
|
err := cmd.Run()
|
||||||
|
t.Log("error:", err)
|
||||||
|
t.Log("stdout:", cmd.Stdout())
|
||||||
|
t.Log("stderr:", cmd.Stderr())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewTimeoutCmd_Echo(t *testing.T) {
|
||||||
|
var cmd = executils.NewTimeoutCmd(10*time.Second, "echo", "-n", "hello")
|
||||||
|
cmd.WithStdout()
|
||||||
|
cmd.WithStderr()
|
||||||
|
err := cmd.Run()
|
||||||
|
t.Log("error:", err)
|
||||||
|
t.Log("stdout:", cmd.Stdout())
|
||||||
|
t.Log("stderr:", cmd.Stderr())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewTimeoutCmd_Echo2(t *testing.T) {
|
||||||
|
var cmd = executils.NewCmd("echo", "hello")
|
||||||
|
cmd.WithStdout()
|
||||||
|
cmd.WithStderr()
|
||||||
|
err := cmd.Run()
|
||||||
|
t.Log("error:", err)
|
||||||
|
t.Log("stdout:", cmd.Stdout())
|
||||||
|
t.Log("raw stdout:", cmd.RawStdout())
|
||||||
|
t.Log("stderr:", cmd.Stderr())
|
||||||
|
t.Log("raw stderr:", cmd.RawStderr())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewTimeoutCmd_Echo3(t *testing.T) {
|
||||||
|
var cmd = executils.NewCmd("echo", "-n", "hello")
|
||||||
|
err := cmd.Run()
|
||||||
|
t.Log("error:", err)
|
||||||
|
t.Log("stdout:", cmd.Stdout())
|
||||||
|
t.Log("stderr:", cmd.Stderr())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCmd_Process(t *testing.T) {
|
||||||
|
var cmd = executils.NewCmd("echo", "-n", "hello")
|
||||||
|
err := cmd.Run()
|
||||||
|
t.Log("error:", err)
|
||||||
|
t.Log(cmd.Process())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewTimeoutCmd_String(t *testing.T) {
|
||||||
|
var cmd = executils.NewCmd("echo", "-n", "hello")
|
||||||
|
t.Log("stdout:", cmd.String())
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user