Golang windows service not writting to logfile - go

I have a simple TCP-server written in Go and running as windows service. It installs/uninstalls just fine, it is working as service and doing it's job but it's not writing a single word in a log file. When I run it simply as an executable in a console - logging works fine. But when it starts as a service - log file is created, application process opens it (thus disallowing to delete it for example) but file remains empty. What I'm doing wrong?
Any word of advice is appreciated.
logging is confured like this
func (p *Program) run() {
exec, _ := os.Executable()
WORK_DIR = filepath.Join(filepath.Dir(exec), "ATT")
_, err := checkDir(WORK_DIR)
if err != nil {
panic("Не удалось создать рабочий каталог")
}
f, err := os.OpenFile(filepath.Join(filepath.Dir(exec), "server.log"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Fatalf("Не удалось создать лог-файл: %v", err)
}
defer f.Close()
wrt := io.MultiWriter(os.Stdout, f)
log.SetOutput(wrt)
server, err := net.Listen("tcp", ":"+PORT)
if err != nil {
log.Fatal(err)
}
defer server.Close()
log.Println("Сервер запущен на порту:", PORT)
for {
connection, err := server.Accept()
if err != nil {
log.Println("Не удалось установить соединение с клиентом", err)
}
go HandleServer(connection)
}
}

The issue you're encountering with logging can be related to file permissions when running as a service. When a service starts, it runs with a different set of permissions than when it runs as a regular executable. In some cases, the service might not have permission to write to a log file in the same location as the executable.
One possible solution is to specify a different location for the log file, such as C:\Windows\System32\LogFiles, which is a common location for log files in Windows. You could also try specifying the absolute path to the log file in the OpenFile call to avoid any confusion about the working directory.
Another potential issue could be with the defer statement that closes the log file. When the service terminates, any deferred statements will be executed, which could cause the log file to be closed before all log messages have been written. To avoid this, you could remove the defer statement and manually close the log file when the service stops.
It may also be a good idea to add error handling to the logging calls to ensure that all log messages are being written even if the log file becomes unavailable. Here is an example:
func (p *Program) run() {
exec, _ := os.Executable()
WORK_DIR = filepath.Join(filepath.Dir(exec), "ATT")
_, err := checkDir(WORK_DIR)
if err != nil {
panic("Не удалось создать рабочий каталог")
}
// Specify the absolute path for the log file
logFilePath := filepath.Join(filepath.Dir(exec), "server.log")
f, err := os.OpenFile(logFilePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Fatalf("Не удалось создать лог-файл: %v", err)
}
// Remove the defer statement to close the log file manually later
// defer f.Close()
wrt := io.MultiWriter(os.Stdout, f)
log.SetOutput(wrt)
server, err := net.Listen("tcp", ":"+PORT)
if err != nil {
log.Fatal(err)
}
defer server.Close()
log.Println("Сервер запущен на порту:", PORT)
for {
connection, err := server.Accept()
if err != nil {
log.Println("Не удалось установить соединение с клиентом", err)
}
go HandleServer(connection)
}
// Manually close the log file when the service stops
f.Close()
}
// Add error handling to the logging calls
func logMessage(message string) {
_, logErr := log.Println(message)
if logErr != nil {
fmt.Printf("Error logging message: %v\n", logErr)
}
}
I hope these suggestions help you resolve the issue with logging in your service. Please let me know.

Related

Handle Http Upload Zip file in Golang

I'm using golang net/http package to retrieve the uploaded zip file via postman.
The attachment file link. It is not dangerous file. Feel free to check out.
Development env
local machine m1 macbook pro golang 1.17.2 - no issue
server docker image golang:1.17.5-stretch - got issue.
Code to capture the post form transSourceFile file.
func HandleFileReqTest(w http.ResponseWriter, req *http.Request, params map[string]string) err {
if err := req.ParseMultipartForm(32 << 20); err != nil {
return err
}
file, header, err := req.FormFile("transSourceFile")
if err != nil {
return err
}
defer file.Close()
fmt.Println("header.Size:", header.Size)
return nil
}
I tried below code also no use
func HandleFileReqTest(w http.ResponseWriter, req *http.Request, params map[string]string) err {
if err := req.ParseForm(); err != nil {
return err
}
req.ParseMultipartForm(32 << 20)
file, header, err := req.FormFile("transSourceFile")
if err != nil {
return err
}
defer file.Close()
fmt.Println("header.Size:", header.Size)
return nil
}
Result:
Local machine got the same file size as the origin file.
Server with golang:1.17.5-stretch got the different file size compare to origin file.
As the result on this, i'm unable to unzip the file in the server. Anyone can help?
You need to copy form file to the actual file:
f, err := os.Create("some.zip")
defer f.Close()
n, err := io.Copy(f, file)
Data isn't being flushed to the file completely. You should close the file first to ensure that the data is fully flushed.
// create a local file filename
dst, err := os.Create("filename.zip")
// save it
fl, err = io.Copy(dst, src)
// Close the file
dst.Close()
stat, _ := dst.Stat()
//Now check the size stat.Size() or header.Size after flushing the file.

Open a Micrsoft DFS share in golang using smb2

I have a dfs share on Windows server 2012. I can open the share and read files from another system in a windows file explorer with a path like: \\dfsserver\usernamepace\Tom\go.png. However, using golang's smb2 package by https://github.com/hirochachacha/go-smb2 I get an error as
response error: The contacted server does not support the indicated
part of the DFS namespace
But if I try to open the file with it's actual share path \\dfsserver\public share\Tom\go.png then the code works fine. So the problem is that I have no knowledge of the actual path during runtime and I want to be able to open the file with path provided by DFS.
Could it be the case that DFS does not work properly with smb2? or some other issues. Thanks in advance for your comments.
func main(){
// actualPath := `\\dfsserver\public share\Tom\go.png`
// dfsPath := `\\dfsserver\usernamespace\Tom\go.png`
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%s", "dfsserver", "445"))
if err != nil {
fmt.Println(err)
}
defer conn.Close()
dial := &smb2.Dialer{
Initiator: &smb2.NTLMInitiator{
User: "user",
Password: "password",
Domain: "dfsserver",
},
}
session, err := dial.Dial(conn)
if err != nil {
fmt.Println(err)
}
defer session.Logoff()
mountPoint, err := session.Mount("usernamespace")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
// error occures here, if the mountPoint was "public share" instead of "usernamespace" then no error
remoteFile, err := mountPoint.Open(`Tom\go.png`)
defer remoteFile.Close()
if err != nil {
fmt.Println(err)
}
}

Problem saving file to network folder when receiving the file through lan - Golang

Probably a confusing title.Let me explain
I have a Go server.Users can upload photos.Server takes those photos and saves it to a network folder that points to a static file server.Testing with localhost everything works fine.However when using my phone connected to LAN, .write([]bytes) throws me an error Z:/xxx.jpg: The network connection was aborted by the local system.
I see that it did receive the bytes successfully checking with len([]bytes).Saving to local disk works fine.
I can not find a reason why that would happen.Since the program receives the bytes,how could it differentiate if they came from localhost or through another device?
Here is a snippet from my code
file, _, err := r.FormFile("uploadFile")
defer file.Close()
fileBytes, err := ioutil.ReadAll(file)
filetype := http.DetectContentType(fileBytes)
switch filetype {
case "image/jpeg", "image/jpg":
case "image/gif", "image/png":
case "application/pdf":
break
default:
renderError(w, "INVALID_FILE_TYPE", http.StatusBadRequest)
return
}
fileName := randToken(12)
fileEndings, err := mime.ExtensionsByType(filetype)
if err != nil {
renderError(w, "CANT_READ_FILE_TYPE", http.StatusInternalServerError)
log.Print(err)
return
}
newPath := uploadPath + fileName + fileEndings[0]
newFile, err := os.Create(newPath)
defer newFile.Close()
if _, err := newFile.Write(fileBytes); err != nil || newFile.Close() != nil{
fmt.Println(err)
}
//success

script command execution hung forever in go program

func Run() error {
log.Info("In Run Command")
cmd := exec.Command("bash", "/opt/AlterKafkaTopic.sh")
stdout, err := cmd.StdoutPipe()
if err != nil {
return err
}
if err = cmd.Start(); err != nil {
return err
}
f, err := os.Create(filepath.Join("/opt/log/", "execution.log"))
if err != nil {
return err
}
if _, err := io.Copy(f, stdout); err != nil {
return err
}
if err := cmd.Wait(); err != nil {
return err
}
return f.Close()
}
I am trying to execute a bash script from go code. The script changes some kafka topic properties. But the execution get hung io.Copy(f, stdout) and does not continue after it.
This program is running on RHEL7.2 server.
Could someone suggest where I am going wrong
From the docs:
Wait will close the pipe after seeing the command exit.
In other words, io.Copy exits when Wait() is called, but Wait is never called because it's blocked by Copy. Either run Copy in a goroutine, or simply assign f to cmd.Stdout:
f, err := os.Create(filepath.Join("/opt/log/", "execution.log"))
// TODO: Handle error
defer f.Close()
cmd := exec.Command("bash", "/opt/AlterKafkaTopic.sh")
cmd.Stdout = f
err = cmd.Run()

cloud storage: unable to upload any content while local with golang

I have this piece of code:
ctx:=context.Background()
cliente, err := storage.NewClient(ctx)
if err != nil {
log.Fatal(err)
}
clienteCS := cliente.Bucket("prueba123456789")
w:=clienteCS.Object("prueba").NewWriter(ctx)
w.ContentType = "text/plain"
if _, err := w.Write([]byte("abcde\n")); err != nil {
log.Fatal(err)
}
attrs, err := clienteCS.Attrs(ctx)
fmt.Printf("atrr: %+v err:%v\n",attrs,err)
When I run this program, in the console I can see the attributes printed from my bucket, that would mean for me that there is nothing wrong with the configuration
, but the problem is that when I see on console.cloud.google.com I see no file on my bucket even on api dashboard does not seem like any api has been called(that peak before the red line is other api I was using) , even though no error is showing on my console that could indicate something went wrong
I just forgot about closing the client, this page alert this problem, always must close the client or the file won't be send, so just need to add some lines:
if err := w.Close(); err != nil {
log.Fatal(err)
return
}

Resources