mirror of
https://github.com/Forceu/Gokapi.git
synced 2026-02-16 13:38:46 -06:00
Fixed building for windows, disable systemd check on windows
This commit is contained in:
@@ -21,6 +21,6 @@ for target in $targets; do
|
||||
rm $output
|
||||
done
|
||||
|
||||
echo "----> Build is complete. List of files at $release_path:"
|
||||
echo "----> Build is complete. List of files at build/:"
|
||||
cd build/
|
||||
ls -l gokapi-*
|
||||
|
||||
15
build/go.sum
15
build/go.sum
@@ -60,6 +60,7 @@ github.com/aws/aws-sdk-go v1.48.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3Tju
|
||||
github.com/aws/aws-sdk-go v1.48.2/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
|
||||
github.com/aws/aws-sdk-go v1.49.22/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
|
||||
github.com/aws/aws-sdk-go v1.51.7/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
|
||||
github.com/aws/aws-sdk-go v1.51.25/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
@@ -399,6 +400,7 @@ golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf
|
||||
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -415,6 +417,7 @@ golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQz
|
||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
|
||||
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
||||
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ=
|
||||
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@@ -445,6 +448,7 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -497,6 +501,7 @@ golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -515,6 +520,7 @@ golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn
|
||||
golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM=
|
||||
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
||||
golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
|
||||
golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -531,6 +537,7 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -590,6 +597,7 @@ golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
@@ -601,6 +609,7 @@ golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww=
|
||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -679,6 +688,7 @@ golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg
|
||||
golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
|
||||
golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -821,21 +831,26 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
|
||||
lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
modernc.org/cc/v3 v3.41.0/go.mod h1:Ni4zjJYJ04CDOhG7dn640WGfwBzfE0ecX8TyMB0Fv0Y=
|
||||
modernc.org/cc/v4 v4.19.5/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
|
||||
modernc.org/cc/v4 v4.20.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
|
||||
modernc.org/ccgo/v3 v3.16.15/go.mod h1:yT7B+/E2m43tmMOT51GMoM98/MtHIcQQSleGnddkUNI=
|
||||
modernc.org/ccgo/v3 v3.17.0/go.mod h1:Sg3fwVpmLvCUTaqEUjiBDAvshIaKDB0RXaf+zgqFu8I=
|
||||
modernc.org/ccgo/v4 v4.13.1/go.mod h1:Td6RI9W9G2ZpKHaJ7UeGEiB2aIpoDqLBnm4wtkbJTbQ=
|
||||
modernc.org/ccgo/v4 v4.16.0/go.mod h1:dkNyWIjFrVIZ68DTo36vHK+6/ShBn4ysU61So6PIqCI=
|
||||
modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
|
||||
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
|
||||
modernc.org/libc v1.34.9/go.mod h1:YAXkAZ8ktnkCKaN9sw/UDeUVkGYJ/YquGO4FTi5nmHE=
|
||||
modernc.org/libc v1.40.5/go.mod h1:YAXkAZ8ktnkCKaN9sw/UDeUVkGYJ/YquGO4FTi5nmHE=
|
||||
modernc.org/libc v1.47.0/go.mod h1:gzCncw0a74aCiVqHeWAYHHaW//fkSHHS/3S/gfhLlCI=
|
||||
modernc.org/libc v1.49.3/go.mod h1:yMZuGkn7pXbKfoT/M35gFJOAEdSKdxL0q64sF7KqCDo=
|
||||
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
||||
modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E=
|
||||
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
|
||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
|
||||
modernc.org/sqlite v1.27.0/go.mod h1:Qxpazz0zH8Z1xCFyi5GSL3FzbtZ3fvbjmywNogldEW0=
|
||||
modernc.org/sqlite v1.28.0/go.mod h1:Qxpazz0zH8Z1xCFyi5GSL3FzbtZ3fvbjmywNogldEW0=
|
||||
modernc.org/sqlite v1.29.5/go.mod h1:S02dvcmm7TnTRvGhv8IGYyLnIt7AS2KPaB1F/71p75U=
|
||||
modernc.org/sqlite v1.29.8/go.mod h1:lQPm27iqa4UNZpmr4Aor0MH0HkCLbt1huYDfWylLZFk=
|
||||
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
|
||||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
|
||||
@@ -1,158 +1,24 @@
|
||||
//go:build !linux
|
||||
|
||||
package systemd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// InstallService installs Gokapi as a systemd service
|
||||
func InstallService() {
|
||||
checkRunAsRoot()
|
||||
checkSystemdOs()
|
||||
|
||||
fmt.Println("Installing Gokapi as a service...")
|
||||
|
||||
// Check if the service file already exists
|
||||
if _, err := os.Stat("/usr/lib/systemd/system/gokapi.service"); err == nil {
|
||||
fmt.Println("Service file already exists. Reinstalling it")
|
||||
}
|
||||
|
||||
// Find the path to the current executable and it's directory
|
||||
executablePath, err := os.Executable()
|
||||
if err != nil {
|
||||
fmt.Println("Error getting executable path: ", err)
|
||||
os.Exit(6)
|
||||
}
|
||||
executableDir := filepath.Dir(executablePath)
|
||||
|
||||
username := getUserInvokingSudo(executablePath)
|
||||
fmt.Println("Running service as user", username)
|
||||
|
||||
// Create the service file
|
||||
serviceFileContents := createSystemdFileContent(executablePath, executableDir, username)
|
||||
|
||||
err = os.WriteFile("/usr/lib/systemd/system/gokapi.service", serviceFileContents, 0644)
|
||||
if err != nil {
|
||||
fmt.Println("Error writing service data to file: ", err)
|
||||
os.Exit(3)
|
||||
}
|
||||
|
||||
systemctlCmd("daemon-reload")
|
||||
systemctlCmd("enable", "gokapi.service")
|
||||
systemctlCmd("start", "gokapi.service")
|
||||
|
||||
fmt.Println("Service installed and started successfully.")
|
||||
fmt.Println("The Gokapi executable found at " + executablePath + " will now run on startup in the background.")
|
||||
fmt.Println("Please do not remove the executable file from that location or the service will not start.")
|
||||
|
||||
// Exit the program
|
||||
os.Exit(0)
|
||||
|
||||
invalidOS()
|
||||
}
|
||||
|
||||
// UninstallService uninstalls Gokapi as a systemd service
|
||||
func UninstallService() {
|
||||
checkRunAsRoot()
|
||||
checkSystemdOs()
|
||||
|
||||
fmt.Println("Uninstalling Gokapi systemd service...")
|
||||
|
||||
// Check if the service file exists
|
||||
if _, err := os.Stat("/usr/lib/systemd/system/gokapi.service"); os.IsNotExist(err) {
|
||||
fmt.Println("Service does not exist in systemd. Nothing to uninstall.")
|
||||
os.Exit(3)
|
||||
}
|
||||
systemctlCmd("stop", "gokapi.service")
|
||||
systemctlCmd("disable", "gokapi.service")
|
||||
// Remove the service file
|
||||
fmt.Println("Removing the service file...")
|
||||
err := os.Remove("/usr/lib/systemd/system/gokapi.service")
|
||||
if err != nil {
|
||||
fmt.Println("Error removing service file: ", err)
|
||||
os.Exit(4)
|
||||
}
|
||||
|
||||
systemctlCmd("daemon-reload")
|
||||
fmt.Println("Service uninstalled successfully.")
|
||||
|
||||
// Exit the program
|
||||
os.Exit(0)
|
||||
invalidOS()
|
||||
}
|
||||
|
||||
// checkRunAsRoot displays an error message and exits the program if not run as root
|
||||
func checkRunAsRoot() {
|
||||
if os.Geteuid() != 0 {
|
||||
fmt.Println("This feature requires root privileges.")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// checkSystemdOs displays an error message and exits the program if the OS is not systemd based
|
||||
func checkSystemdOs() {
|
||||
if _, err := os.Stat("/usr/lib/systemd/system"); os.IsNotExist(err) {
|
||||
fmt.Println("This feature is only supported on systems using systemd.")
|
||||
os.Exit(2)
|
||||
}
|
||||
}
|
||||
|
||||
// systemctlCmd runs the command systemctl with the provided arguments. It displays an error message and exits the program
|
||||
// if an error is encountered
|
||||
func systemctlCmd(arg ...string) {
|
||||
err := exec.Command("systemctl", arg...).Run()
|
||||
if err != nil {
|
||||
fmt.Println("Error executing systemctl "+arg[0]+": ", err)
|
||||
os.Exit(4)
|
||||
}
|
||||
}
|
||||
|
||||
func getUserInvokingSudo(executablePath string) string {
|
||||
username := os.Getenv("SUDO_USER")
|
||||
if username == "root" || username == "" {
|
||||
fmt.Println("WARNING! Could not determine user invoking sudo.")
|
||||
usernameFromExecutable, err := getUsernameOfFileOwner(executablePath)
|
||||
if err != nil {
|
||||
fmt.Println("Could not determine username from file owner:", err)
|
||||
os.Exit(6)
|
||||
}
|
||||
username = usernameFromExecutable
|
||||
}
|
||||
if username == "root" {
|
||||
fmt.Println("Could not determine username other than root. Not running service as root.")
|
||||
os.Exit(6)
|
||||
}
|
||||
return username
|
||||
}
|
||||
|
||||
func getUsernameOfFileOwner(filename string) (string, error) {
|
||||
fileInfo, err := os.Stat(filename)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
fileUid := fileInfo.Sys().(*syscall.Stat_t).Uid
|
||||
fileUser, err := user.LookupId(fmt.Sprintf("%d", fileUid))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fileUser.Username, nil
|
||||
}
|
||||
|
||||
// createSystemdFileContent returns a byte array with the content of the systemd file to be written
|
||||
func createSystemdFileContent(executablePath, executableDir, username string) []byte {
|
||||
return []byte(`[Unit]
|
||||
Description=Gokapi
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=` + executablePath + `
|
||||
WorkingDirectory=` + executableDir + `
|
||||
User=` + username + `
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target`)
|
||||
// invalidOS displays an error message and exits the program, as systemd is not supported on Windows
|
||||
func invalidOS() {
|
||||
fmt.Println("This feature is only supported on systems using systemd.")
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
160
internal/helper/systemd/Systemd_linux.go
Normal file
160
internal/helper/systemd/Systemd_linux.go
Normal file
@@ -0,0 +1,160 @@
|
||||
//go:build linux
|
||||
|
||||
package systemd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// InstallService installs Gokapi as a systemd service
|
||||
func InstallService() {
|
||||
checkRunAsRoot()
|
||||
checkSystemdOs()
|
||||
|
||||
fmt.Println("Installing Gokapi as a service...")
|
||||
|
||||
// Check if the service file already exists
|
||||
if _, err := os.Stat("/usr/lib/systemd/system/gokapi.service"); err == nil {
|
||||
fmt.Println("Service file already exists. Reinstalling it")
|
||||
}
|
||||
|
||||
// Find the path to the current executable and it's directory
|
||||
executablePath, err := os.Executable()
|
||||
if err != nil {
|
||||
fmt.Println("Error getting executable path: ", err)
|
||||
os.Exit(6)
|
||||
}
|
||||
executableDir := filepath.Dir(executablePath)
|
||||
|
||||
username := getUserInvokingSudo(executablePath)
|
||||
fmt.Println("Running service as user", username)
|
||||
|
||||
// Create the service file
|
||||
serviceFileContents := createSystemdFileContent(executablePath, executableDir, username)
|
||||
|
||||
err = os.WriteFile("/usr/lib/systemd/system/gokapi.service", serviceFileContents, 0644)
|
||||
if err != nil {
|
||||
fmt.Println("Error writing service data to file: ", err)
|
||||
os.Exit(3)
|
||||
}
|
||||
|
||||
systemctlCmd("daemon-reload")
|
||||
systemctlCmd("enable", "gokapi.service")
|
||||
systemctlCmd("start", "gokapi.service")
|
||||
|
||||
fmt.Println("Service installed and started successfully.")
|
||||
fmt.Println("The Gokapi executable found at " + executablePath + " will now run on startup in the background.")
|
||||
fmt.Println("Please do not remove the executable file from that location or the service will not start.")
|
||||
|
||||
// Exit the program
|
||||
os.Exit(0)
|
||||
|
||||
}
|
||||
|
||||
// UninstallService uninstalls Gokapi as a systemd service
|
||||
func UninstallService() {
|
||||
checkRunAsRoot()
|
||||
checkSystemdOs()
|
||||
|
||||
fmt.Println("Uninstalling Gokapi systemd service...")
|
||||
|
||||
// Check if the service file exists
|
||||
if _, err := os.Stat("/usr/lib/systemd/system/gokapi.service"); os.IsNotExist(err) {
|
||||
fmt.Println("Service does not exist in systemd. Nothing to uninstall.")
|
||||
os.Exit(3)
|
||||
}
|
||||
systemctlCmd("stop", "gokapi.service")
|
||||
systemctlCmd("disable", "gokapi.service")
|
||||
// Remove the service file
|
||||
fmt.Println("Removing the service file...")
|
||||
err := os.Remove("/usr/lib/systemd/system/gokapi.service")
|
||||
if err != nil {
|
||||
fmt.Println("Error removing service file: ", err)
|
||||
os.Exit(4)
|
||||
}
|
||||
|
||||
systemctlCmd("daemon-reload")
|
||||
fmt.Println("Service uninstalled successfully.")
|
||||
|
||||
// Exit the program
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// checkRunAsRoot displays an error message and exits the program if not run as root
|
||||
func checkRunAsRoot() {
|
||||
if os.Geteuid() != 0 {
|
||||
fmt.Println("This feature requires root privileges.")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// checkSystemdOs displays an error message and exits the program if the OS is not systemd based
|
||||
func checkSystemdOs() {
|
||||
if _, err := os.Stat("/usr/lib/systemd/system"); os.IsNotExist(err) {
|
||||
fmt.Println("This feature is only supported on systems using systemd.")
|
||||
os.Exit(2)
|
||||
}
|
||||
}
|
||||
|
||||
// systemctlCmd runs the command systemctl with the provided arguments. It displays an error message and exits the program
|
||||
// if an error is encountered
|
||||
func systemctlCmd(arg ...string) {
|
||||
err := exec.Command("systemctl", arg...).Run()
|
||||
if err != nil {
|
||||
fmt.Println("Error executing systemctl "+arg[0]+": ", err)
|
||||
os.Exit(4)
|
||||
}
|
||||
}
|
||||
|
||||
func getUserInvokingSudo(executablePath string) string {
|
||||
username := os.Getenv("SUDO_USER")
|
||||
if username == "root" || username == "" {
|
||||
fmt.Println("WARNING! Could not determine user invoking sudo.")
|
||||
usernameFromExecutable, err := getUsernameOfFileOwner(executablePath)
|
||||
if err != nil {
|
||||
fmt.Println("Could not determine username from file owner:", err)
|
||||
os.Exit(6)
|
||||
}
|
||||
username = usernameFromExecutable
|
||||
}
|
||||
if username == "root" {
|
||||
fmt.Println("Could not determine username other than root. Not running service as root.")
|
||||
os.Exit(6)
|
||||
}
|
||||
return username
|
||||
}
|
||||
|
||||
func getUsernameOfFileOwner(filename string) (string, error) {
|
||||
fileInfo, err := os.Stat(filename)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
fileUid := fileInfo.Sys().(*syscall.Stat_t).Uid
|
||||
fileUser, err := user.LookupId(fmt.Sprintf("%d", fileUid))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fileUser.Username, nil
|
||||
}
|
||||
|
||||
// createSystemdFileContent returns a byte array with the content of the systemd file to be written
|
||||
func createSystemdFileContent(executablePath, executableDir, username string) []byte {
|
||||
return []byte(`[Unit]
|
||||
Description=Gokapi
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=` + executablePath + `
|
||||
WorkingDirectory=` + executableDir + `
|
||||
User=` + username + `
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target`)
|
||||
}
|
||||
Reference in New Issue
Block a user