diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
new file mode 100644
index 0000000..f899017
--- /dev/null
+++ b/.github/workflows/ci.yaml
@@ -0,0 +1,29 @@
+name: Continuous Integration
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+ branches:
+ - main
+
+jobs:
+ build:
+ name: Build and Test
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Check out code
+ uses: actions/checkout@v2
+
+ - name: Set up Go
+ uses: actions/setup-go@v2
+ with:
+ go-version: 1.21.5
+
+ - name: Build
+ run: go build -v ./...
+
+ - name: Run tests
+ run: go test -v ./...
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
new file mode 100644
index 0000000..49c0d6b
--- /dev/null
+++ b/.github/workflows/release.yaml
@@ -0,0 +1,29 @@
+name: Release
+
+on:
+ push:
+ tags:
+ - '*'
+ workflow_dispatch:
+ inputs:
+ version:
+ description: 'Version (e.g., 1.0.0)'
+ required: true
+
+jobs:
+ goreleaser:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+
+ - name: Set up Go
+ uses: actions/setup-go@v2
+ with:
+ go-version: 1.21.5
+
+ - name: Run GoReleaser
+ if: github.event_name == 'workflow_dispatch'
+ run: goreleaser release --rm-dist --release-notes "Release version ${{ github.event.inputs.version }}"
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitignore b/.gitignore
index 3b735ec..1ef478b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,12 +1,10 @@
-# If you prefer the allow list template instead of the deny list, see community template:
-# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
-#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
+osmon
# Test binary, built with `go test -c`
*.test
@@ -19,3 +17,24 @@
# Go workspace file
go.work
+
+# Ignore JetBrains IntelliJ IDEA project files
+.idea/
+
+# Ignore Visual Studio Code project files
+.vscode/
+
+# Ignore temporary directories and files
+.idea/
+.vscode/
+.idea_modules/
+.idea_caches/
+out/
+.idea.vim/
+.idea_workspace/
+
+# Ignore project files generated by IntelliJ IDEA
+*.iml
+*.ipr
+*.iws
+*.idea_modules
\ No newline at end of file
diff --git a/.goreleaser.yml b/.goreleaser.yml
new file mode 100644
index 0000000..e3e4be8
--- /dev/null
+++ b/.goreleaser.yml
@@ -0,0 +1,54 @@
+# .goreleaser.yml
+# This is the GoReleaser configuration file which defines how to build, package, and release your application.
+
+project_name: osmon # The name of your project.
+
+# Build section defines how your application should be built.
+builds:
+ - id: osmon
+ main: . # Path to the main source file or directory of your program.
+ binary: osmon # Name of the compiled binary.
+ goos: # List of target operating systems.
+ - linux
+ - darwin
+ goarch: # List of target architectures.
+ - amd64
+ - arm64
+ env: # Environment variables to be set during the build process.
+ - CGO_ENABLED=0
+ ldflags: # Flags to pass to the go compiler.
+ - -s -w
+
+# Archives section defines how to package your binary.
+archives:
+ - id: archive
+ builds:
+ - osmon
+ format: tar.gz # Format for Linux binaries.
+ format_overrides:
+ - goos: darwin
+ format: zip # Format for macOS binaries.
+ wrap_in_directory: true
+ files: # Additional files to include in the archive.
+ - LICENSE
+ - README.md
+
+# Release section configures how to handle GitHub releases.
+release:
+ github:
+ owner: debek
+ name: osmon
+ draft: true # Indicates whether the release should be a draft.
+ prerelease: auto # Automatically set whether the release is a prerelease based on the tag.
+
+# Checksum section generates checksums of your binaries.
+checksum:
+ name_template: 'checksums.txt'
+
+# Snapshot section configures the creation of snapshots.
+snapshot:
+ name_template: "{{ .Tag }}-next" # Template for naming snapshot releases.
+
+# Changelog section configures how the changelog should be handled.
+changelog:
+ skip: false # Indicates whether to skip generating the changelog.
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/aws.xml b/.idea/aws.xml
new file mode 100644
index 0000000..ec328d0
--- /dev/null
+++ b/.idea/aws.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..919ce1f
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..a55e7a1
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..639900d
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..1867f5f
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/osmon.iml b/.idea/osmon.iml
new file mode 100644
index 0000000..25ed3f6
--- /dev/null
+++ b/.idea/osmon.iml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CONTRIBUTE.md b/CONTRIBUTE.md
new file mode 100644
index 0000000..eb39c02
--- /dev/null
+++ b/CONTRIBUTE.md
@@ -0,0 +1,32 @@
+# Contributing to osmon
+
+Thank you for your interest in contributing to osmon! All contributions, whether code, bug reports, or feature suggestions, are greatly appreciated.
+
+## How Can I Contribute?
+
+### Reporting Bugs and Suggesting Features
+- If you encounter a bug or have an idea for a new feature, please create an issue in our GitHub repository.
+- Describe the bug or feature as detailed as possible to help us understand your intentions.
+
+### Creating Pull Requests
+- Fork the repository.
+- Create a new branch for your changes (`git checkout -b my-new-feature`).
+- Make your changes in the code.
+- Ensure code is well-formatted and follows the project's coding standards.
+- Commit your changes (`git commit -am 'Add some feature'`).
+- Push to your fork (`git push origin my-new-feature`).
+- Submit a Pull Request to our repository.
+
+### Guidelines
+- Make sure your changes are well documented.
+- Add tests for new features.
+- Follow the established coding standards.
+
+## Coding and Testing
+- We encourage clear and understandable coding.
+- Unit tests are an essential part of development. Try to maintain high test coverage.
+
+## Questions?
+If you have any questions or concerns, don't hesitate to ask. We are here to help!
+
+Thank you for your contributions to the osmon project!
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..2ba1b90
--- /dev/null
+++ b/README.md
@@ -0,0 +1,107 @@
+# osmon
+
+**osmon** is a command-line tool written in Go that provides quick access to basic system information. With **osmon**, you can easily access details such as your host's IP address, system load, memory usage, logged-in users, and much more.
+
+## Features
+
+- Displaying your host's name and IP address.
+- Showing the current system load averages.
+- Overview of memory usage statistics, including total memory, used memory, and available memory.
+- Listing logged-in users and their respective terminals.
+
+[//]: # (## Demo Video)
+
+[//]: # ()
+[//]: # (Check out this demo of **osmon** in action:)
+
+[//]: # ()
+[//]: # ([![Demo Video](http://img.youtube.com/vi/ID_TWOJEGO_FILMU/0.jpg)](http://www.youtube.com/watch?v=ID_TWOJEGO_FILMU "osmon Demo"))
+
+## Applications
+
+### Monitoring After SSH Login
+
+**osmon** is an ideal tool for a quick overview of a server's status upon SSH login. You can configure your shell to automatically run `osmon` every time you log in, providing an immediate snapshot of the server's status.
+
+Example:
+
+- Configure your `.bashrc` or `.zshrc` to run `osmon` upon every login, allowing you to immediately assess the state of the server.
+
+### Debugging
+
+**osmon** can be an invaluable tool for debugging performance issues. By running `osmon`, you can quickly identify if high system load is caused by memory, CPU, or network activity.
+
+Example:
+
+- If you notice that your application is running slower than usual, you can use `osmon` to check if the system is under heavy load.
+
+### Installation
+
+You can install **osmon** using the Go tool:
+
+
+`go install github.com/yourusername/osmon@latest`
+
+After installation, add the Go binary path to your system's PATH to access the `osmon` command from anywhere:
+
+
+`export PATH=$PATH:~/go/bin`
+
+### Usage
+
+**osmon** offers various command-line options for tailored usage. Below are the available flags and their descriptions:
+
+- `-h`: Display help information. \[...\]
+- `-v`: Display the version of the application. \[...\]
+- `-i` or `--interval`: Set the interval for refreshing the display in seconds. \[...\]
+
+#### Basic Usage
+
+To simply display the system information, run the `osmon` command without any flags:
+
+
+`osmon`
+
+#### Continuous Monitoring
+
+If you want to continuously monitor your system's status with a specific refresh interval, use the `-i` flag with your desired interval in seconds:
+
+
+```bash
+osmon -i 5
+```
+
+### Binary Release Installation (Optional)
+
+If you release a binary version of **osmon**, users can follow these steps:
+
+1. Download the binary from the "Releases" section of your GitHub repository.
+
+2. Move the binary to a directory in your PATH, for example, `/usr/local/bin`:
+
+
+1. `mv osmon /usr/local/bin/osmon chmod +x /usr/local/bin/osmon`
+
+
+## Compatibility
+
+- **osmon** is compatible with Linux and macOS systems.
+
+## Contributing
+
+If you're interested in contributing to the osmon project, please check our [contribution guidelines](https://chat.openai.com/g/g-yxXXjJ1If-it-gpt4/c/CONTRIBUTE.md). All contributions, from bug reporting to new feature suggestions, are highly appreciated.
+
+## License
+
+This project is available under the [MIT License](https://chat.openai.com/g/g-yxXXjJ1If-it-gpt4/c/0c1a0ed0-de56-4ded-8159-e19be6cae7bc).
+
+## Acknowledgments
+
+Special thanks to the Go community for creating excellent libraries like `github.com/shirou/gopsutil`, which make it easier to gather system information.
+
+## TO DO
+
+- **Information about IOBS and IOPS**: Include details about read and write operations, and possibly any limits.
+- **Outgoing and Incoming Connections**: Display connections in kilobits or megabits.
+- **Number of Connections**: Show the count of incoming and outgoing connections.
+- **Kernel Version**: Add information about the kernel version.
\ No newline at end of file
diff --git a/display.go b/display.go
new file mode 100644
index 0000000..14eb950
--- /dev/null
+++ b/display.go
@@ -0,0 +1,162 @@
+package main
+
+import (
+ "fmt"
+ "github.com/shirou/gopsutil/disk"
+ "github.com/shirou/gopsutil/load"
+ "github.com/shirou/gopsutil/mem"
+ "net"
+ "os"
+ "os/exec"
+ "os/user"
+ "runtime"
+ "strings"
+ "time"
+)
+
+func displaySystemInfoInInterval(interval time.Duration) {
+ for {
+ clearScreen() // Pozostawione w tej funkcji
+ displaySystemInfo()
+ time.Sleep(interval)
+ }
+}
+
+func displaySystemInfo() {
+ // Usunięto wywołanie clearScreen() stąd
+ currentUser, err := user.Current()
+ if err != nil {
+ fmt.Printf("Failed to get current user: %s\n", err)
+ return
+ }
+ userName := currentUser.Username
+
+ currentPTS, err := getCurrentPTS()
+ if err != nil {
+ fmt.Printf("Failed to get current PTS: %s\n", err)
+ return
+ }
+
+ activeUsers, err := getActiveUsers()
+ if err != nil {
+ fmt.Printf("Error getting active users: %s\n", err)
+ return
+ }
+
+ hostName, err := os.Hostname()
+ if err != nil {
+ fmt.Printf("Failed to get hostname: %s\n", err)
+ return
+ }
+
+ conn, err := net.Dial("udp", "8.8.8.8:80")
+ if err != nil {
+ fmt.Printf("Failed to dial: %s\n", err)
+ return
+ }
+ localAddr := conn.LocalAddr().(*net.UDPAddr)
+ ip := localAddr.IP.String()
+ conn.Close()
+
+ uptime, err := getUptime()
+ if err != nil {
+ fmt.Printf("Failed to get uptime: %s\n", err)
+ return
+ }
+ upDays := uptime / (24 * time.Hour)
+ upHours := (uptime % (24 * time.Hour)) / time.Hour
+ upMins := (uptime % time.Hour) / time.Minute
+ upSecs := (uptime % time.Minute) / time.Second
+
+ vmStat, err := mem.VirtualMemory()
+ if err != nil {
+ fmt.Printf("Failed to get virtual memory info: %s\n", err)
+ return
+ }
+ memoryUsed := vmStat.Used / 1024 / 1024
+ memoryTotal := vmStat.Total / 1024 / 1024
+ memoryAvailable := vmStat.Available / 1024 / 1024
+ usedMemoryPercent := (float64(memoryUsed) / float64(memoryTotal)) * 100
+ freeMemoryPercent := 100 - usedMemoryPercent
+
+ cpuInfo, err := getCPUInfo()
+ if err != nil {
+ fmt.Printf("Failed to get CPU info: %s\n", err)
+ return
+ }
+
+ cpuCores, err := getCPUCores()
+ if err != nil {
+ fmt.Printf("Failed to get CPU cores: %s\n", err)
+ return
+ }
+
+ loadAvg, err := load.Avg()
+ if err != nil {
+ fmt.Printf("Failed to get load average: %s\n", err)
+ return
+ }
+
+ diskStat, err := disk.Usage("/")
+ if err != nil {
+ fmt.Printf("Failed to get disk usage: %s\n", err)
+ return
+ }
+
+ memoryUsedGB := float64(memoryUsed) / 1024
+ memoryTotalGB := float64(memoryTotal) / 1024
+ memoryAvailableGB := float64(memoryAvailable) / 1024
+
+ diskFree := float64(diskStat.Free) / 1024 / 1024 / 1024
+ diskTotal := float64(diskStat.Total) / 1024 / 1024 / 1024
+ diskUsed := diskTotal - diskFree
+ freeDiskPercent := (diskFree / diskTotal) * 100
+
+ const (
+ resetColor = "\033[0m"
+ bold = "\033[1m"
+ cyan = "\033[36m"
+ )
+ fmt.Println(cyan + "======================================OSMON======================================" + resetColor)
+ fmt.Printf("%s%s - CPU.................:%s %s (%d cores)%s\n", bold, cyan, resetColor, cpuInfo, cpuCores, resetColor)
+ fmt.Printf("%s%s - Load................:%s %.2f %.2f %.2f%s\n", bold, cyan, resetColor, loadAvg.Load1, loadAvg.Load5, loadAvg.Load15, resetColor)
+ fmt.Printf("%s%s - Memory..............:%s %.2f GB / %.2f GB (%.2f GB remaining, %.2f%% free)%s\n",
+ bold, cyan, resetColor, memoryUsedGB, memoryTotalGB, memoryAvailableGB, freeMemoryPercent, resetColor)
+ fmt.Printf("%s%s - Disk space /........:%s %.2f GB / %.2f GB (%.2f GB remaining, %.2f%% free)%s\n", bold, cyan, resetColor, diskUsed, diskTotal, diskFree, freeDiskPercent, resetColor)
+ fmt.Printf("%s%s - Processes...........:%s %d running%s\n", bold, cyan, resetColor, getProcessCount(), resetColor)
+ fmt.Printf("%s%s - System uptime.......:%s %d days %d hours %d minutes %d seconds%s\n", bold, cyan, resetColor, upDays, upHours, upMins, upSecs, resetColor)
+ fmt.Printf("%s%s - Hostname / IP.......:%s %s / %s%s\n", bold, cyan, resetColor, hostName, ip, resetColor)
+ fmt.Printf("%s%s - Release.............:%s %s%s\n", bold, cyan, resetColor, getOSRelease(), resetColor)
+ fmt.Printf("%s%s - Current user........:%s [%s: %s]%s\n", bold, cyan, resetColor, currentPTS, userName, resetColor)
+ if runtime.GOOS == "linux" {
+ fmt.Printf("%s%s - Active users........:%s ", bold, cyan, resetColor)
+ for terminal, users := range activeUsers {
+ fmt.Printf("[%s: %s] ", terminal, strings.Join(users, ", "))
+ }
+ fmt.Println()
+ }
+ fmt.Println(cyan + "=================================================================================" + resetColor)
+}
+
+func clearScreen() {
+ if runtime.GOOS == "windows" {
+ cmd := exec.Command("cmd", "/c", "cls")
+ cmd.Stdout = os.Stdout
+ cmd.Run()
+ } else {
+ fmt.Print("\033[H\033[2J")
+ }
+}
+
+func displayHelp() {
+ fmt.Println("OSInfo - Display system information with refresh interval")
+ fmt.Println("\nUsage:")
+ fmt.Println(" ./osmon Display system information once")
+ fmt.Println(" ./osmon -i Refresh system information every seconds")
+ fmt.Println(" ./osmon -h/--help Display this help information")
+ fmt.Println(" ./osmon -v/--version Display the version of the application")
+ fmt.Println("\nFlags:")
+ fmt.Println(" -i, --interval Set interval for refreshing the display in seconds")
+ fmt.Println(" -h, --help Display help information")
+ fmt.Println(" -v, --version Display the version of the application")
+}
diff --git a/flags.go b/flags.go
new file mode 100644
index 0000000..ac3b412
--- /dev/null
+++ b/flags.go
@@ -0,0 +1,42 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "strconv"
+)
+
+type intervalFlag struct {
+ set bool
+ value int
+}
+
+// Set jest metodą wywoływaną przez pakiet flag, gdy flaga zostanie ustawiona.
+func (f *intervalFlag) Set(s string) error {
+ f.set = true
+ var err error
+ f.value, err = strconv.Atoi(s)
+ if err != nil {
+ return fmt.Errorf("invalid format for interval: %v", err)
+ }
+ return nil
+}
+
+// String zwraca reprezentację string flagi.
+func (f *intervalFlag) String() string {
+ if !f.set {
+ return "not set"
+ }
+ return fmt.Sprintf("%d", f.value)
+}
+
+func DefineFlags() (intervalFlag, *bool, *bool) {
+ var interval intervalFlag
+ var helpFlag = flag.Bool("h", false, "Display help information (shorthand)")
+ var versionFlag = flag.Bool("v", false, "Display the version of the application (shorthand)")
+
+ flag.Var(&interval, "i", "Set interval for refreshing the display in seconds (shorthand)")
+ flag.Var(&interval, "interval", "Set interval for refreshing the display in seconds")
+
+ return interval, helpFlag, versionFlag
+}
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..dabab06
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,14 @@
+module github.com/debek/osmon
+
+go 1.21.5
+
+require github.com/shirou/gopsutil v3.21.11+incompatible
+
+require (
+ github.com/go-ole/go-ole v1.2.6 // indirect
+ github.com/stretchr/testify v1.8.4 // indirect
+ github.com/tklauser/go-sysconf v0.3.13 // indirect
+ github.com/tklauser/numcpus v0.7.0 // indirect
+ github.com/yusufpapurcu/wmi v1.2.3 // indirect
+ golang.org/x/sys v0.15.0 // indirect
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..6554970
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,21 @@
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
+github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
+github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4=
+github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0=
+github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4=
+github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY=
+github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
+github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
+golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..c6129a7
--- /dev/null
+++ b/main.go
@@ -0,0 +1,43 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "os"
+ "time"
+)
+
+func main() {
+ var interval intervalFlag
+ var helpFlag bool
+ var versionFlag bool
+
+ flag.Usage = displayHelp
+ flag.Var(&interval, "i", "Set interval for refreshing the display in seconds (shorthand)")
+ flag.Var(&interval, "interval", "Set interval for refreshing the display in seconds")
+ flag.BoolVar(&helpFlag, "h", false, "Display help information (shorthand)")
+ flag.BoolVar(&helpFlag, "help", false, "Display help information")
+ flag.BoolVar(&versionFlag, "v", false, "Display the version of the application (shorthand)")
+ flag.BoolVar(&versionFlag, "version", false, "Display the version of the application")
+ flag.Parse()
+
+ if versionFlag {
+ appVersion := os.Getenv("APP_VERSION")
+ if appVersion == "" {
+ appVersion = "development"
+ }
+ fmt.Printf("OSInfo version %s\n", appVersion)
+ os.Exit(0)
+ }
+
+ if helpFlag {
+ displayHelp()
+ os.Exit(0)
+ }
+
+ if interval.set {
+ displaySystemInfoInInterval(time.Duration(interval.value) * time.Second)
+ } else {
+ displaySystemInfo()
+ }
+}
diff --git a/osmon b/osmon
new file mode 100755
index 0000000..7b4507e
Binary files /dev/null and b/osmon differ
diff --git a/system_info.go b/system_info.go
new file mode 100644
index 0000000..4923b28
--- /dev/null
+++ b/system_info.go
@@ -0,0 +1,120 @@
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "os"
+ "os/exec"
+ "runtime"
+ "strconv"
+ "strings"
+ "time"
+)
+
+func getOSRelease() string {
+ if runtime.GOOS == "darwin" {
+ out, err := exec.Command("sw_vers", "-productVersion").Output()
+ if err != nil {
+ return "Unknown"
+ }
+ return "macOS " + strings.TrimSpace(string(out))
+ }
+ if runtime.GOOS == "linux" {
+ file, err := os.Open("/etc/os-release")
+ if err != nil {
+ return "Unknown"
+ }
+ defer file.Close()
+
+ scanner := bufio.NewScanner(file)
+ for scanner.Scan() {
+ line := scanner.Text()
+ if strings.HasPrefix(line, "PRETTY_NAME=") {
+ return strings.Trim(line[13:], "\"")
+ }
+ }
+ }
+ return "Unknown"
+}
+
+func getCPUInfo() (string, error) {
+ if runtime.GOOS == "darwin" {
+ out, err := exec.Command("sysctl", "-n", "machdep.cpu.brand_string").Output()
+ if err != nil {
+ return "", err
+ }
+ return strings.TrimSpace(string(out)), nil
+ }
+ if runtime.GOOS == "linux" {
+ out, err := exec.Command("cat", "/proc/cpuinfo").Output()
+ if err != nil {
+ return "", err
+ }
+ return parseLinuxCPUInfo(string(out)), nil
+ }
+ return "", fmt.Errorf("unsupported platform")
+}
+
+func parseLinuxCPUInfo(info string) string {
+ lines := strings.Split(info, "\n")
+ for _, line := range lines {
+ if strings.HasPrefix(line, "model name") {
+ return strings.TrimSpace(strings.Split(line, ":")[1])
+ }
+ }
+ return "Unknown"
+}
+
+func getCPUCores() (int, error) {
+ if runtime.GOOS == "darwin" {
+ out, err := exec.Command("sysctl", "-n", "hw.ncpu").Output()
+ if err != nil {
+ return 0, err
+ }
+ cores, err := strconv.Atoi(strings.TrimSpace(string(out)))
+ if err != nil {
+ return 0, err
+ }
+ return cores, nil
+ }
+ if runtime.GOOS == "linux" {
+ out, err := exec.Command("grep", "-c", "processor", "/proc/cpuinfo").Output()
+ if err != nil {
+ return 0, err
+ }
+ cores, err := strconv.Atoi(strings.TrimSpace(string(out)))
+ if err != nil {
+ return 0, err
+ }
+ return cores, nil
+ }
+ return 0, fmt.Errorf("unsupported platform")
+}
+
+func getUptime() (time.Duration, error) {
+ if runtime.GOOS == "darwin" {
+ out, err := exec.Command("sysctl", "-n", "kern.boottime").Output()
+ if err != nil {
+ return 0, err
+ }
+ uptimeString := strings.Split(strings.Split(string(out), "=")[1], ",")[0]
+ uptimeSec, err := strconv.ParseInt(strings.TrimSpace(uptimeString), 10, 64)
+ if err != nil {
+ return 0, err
+ }
+ return time.Since(time.Unix(uptimeSec, 0)), nil
+ }
+ if runtime.GOOS == "linux" {
+ out, err := exec.Command("cat", "/proc/uptime").Output()
+ if err != nil {
+ return 0, err
+ }
+ uptimeString := strings.Fields(string(out))[0]
+ uptimeSec, err := strconv.ParseFloat(uptimeString, 64)
+ if err != nil {
+ return 0, err
+ }
+ return time.Duration(uptimeSec) * time.Second, nil
+ }
+ return 0, fmt.Errorf("unsupported platform")
+}
diff --git a/user_info.go b/user_info.go
new file mode 100644
index 0000000..bad3f2d
--- /dev/null
+++ b/user_info.go
@@ -0,0 +1,91 @@
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "os"
+ "os/exec"
+ "regexp"
+ "runtime"
+ "strings"
+)
+
+func getActiveUsers() (map[string][]string, error) {
+ out, err := exec.Command("ps", "aux").Output()
+ if err != nil {
+ return nil, err
+ }
+
+ activeUsers := make(map[string][]string)
+ lines := strings.Split(string(out), "\n")
+ for _, line := range lines {
+ fields := strings.Fields(line)
+ if len(fields) > 1 {
+ user := fields[0]
+ tty := fields[6]
+ if strings.HasPrefix(tty, "pts") { // Dodano sprawdzenie czy tty zaczyna się od "pts"
+ if _, found := activeUsers[tty]; !found {
+ activeUsers[tty] = []string{}
+ }
+ fullUserName, err := getFullUserName(user)
+ if err == nil {
+ user = fullUserName
+ }
+ if !contains(activeUsers[tty], user) {
+ activeUsers[tty] = append(activeUsers[tty], user)
+ }
+ }
+ }
+ }
+ return activeUsers, nil
+}
+
+func getFullUserName(shortName string) (string, error) {
+ file, err := os.Open("/etc/passwd")
+ if err != nil {
+ return shortName, err
+ }
+ defer file.Close()
+
+ trimmedShortName := strings.TrimSuffix(shortName, "+")
+
+ scanner := bufio.NewScanner(file)
+ for scanner.Scan() {
+ line := scanner.Text()
+ parts := strings.Split(line, ":")
+ if len(parts) > 0 {
+ userName := parts[0]
+ if strings.HasPrefix(userName, trimmedShortName) {
+ return userName, nil
+ }
+ }
+ }
+ if err := scanner.Err(); err != nil {
+ return shortName, err
+ }
+ return shortName, nil
+}
+
+func getCurrentPTS() (string, error) {
+ if runtime.GOOS == "linux" {
+ tty, err := os.Readlink("/proc/self/fd/0")
+ if err != nil {
+ return "", err
+ }
+ re := regexp.MustCompile(`(pts/\d+|ttyS?\d*)`)
+ pts := re.FindString(tty)
+ if pts == "" {
+ return "", fmt.Errorf("could not parse PTS")
+ }
+ return pts, nil
+ } else if runtime.GOOS == "darwin" {
+ ttyNumber := os.Getenv("_P9K_SSH_TTY")
+ re := regexp.MustCompile(`(ttys?\d*)`)
+ pts := re.FindString(ttyNumber)
+ if ttyNumber == "" {
+ return "not available", nil
+ }
+ return pts, nil
+ }
+ return "", fmt.Errorf("unsupported platform")
+}
diff --git a/utility.go b/utility.go
new file mode 100644
index 0000000..bc3dec5
--- /dev/null
+++ b/utility.go
@@ -0,0 +1,20 @@
+package main
+
+import "github.com/shirou/gopsutil/process"
+
+func contains(slice []string, item string) bool {
+ for _, s := range slice {
+ if s == item {
+ return true
+ }
+ }
+ return false
+}
+
+func getProcessCount() int {
+ pids, err := process.Pids()
+ if err != nil {
+ return 0
+ }
+ return len(pids)
+}