Skip to content

Commit aa31707

Browse files
authored
Update README.md
1 parent cba8c80 commit aa31707

File tree

1 file changed

+109
-81
lines changed

1 file changed

+109
-81
lines changed

README.md

+109-81
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
[![License](https://img.shields.io/github/license/diffstorm/processWatchdog)](https://github.com/diffstorm/processWatchdog/blob/main/LICENSE)
55
[![Language](https://img.shields.io/github/languages/top/diffstorm/processWatchdog)](https://github.com/diffstorm/processWatchdog)
66

7+
_It will start, monitor and restart applications if they crash or stop sending heartbeat._
8+
79
The Process Watchdog is a Linux-based utility designed to start, monitor and manage processes specified in a configuration file. It ensures the continuous operation of these processes by periodically checking their status and restarting them if necessary.
810

911
## Overview
@@ -64,7 +66,7 @@ nWdtApps = 4
6466
- `cmd` : Command to start the application.
6567

6668
## Example Heartbeat Message Code
67-
The managed processes must send a message containing their PID over UDP. Below are example heartbeat message codes in various languages.
69+
The managed processes must send a message containing their PID with prefix `p` (Ex: `p12345`) over UDP. Below are example heartbeat message codes in various languages.
6870

6971
### Java
7072
```java
@@ -75,14 +77,14 @@ import java.net.InetAddress;
7577

7678
public class ProcessHeartbeat {
7779
public static void sendPIDOverUDP(int port) {
78-
try {
79-
String host = "127.0.0.255";
80-
String pid = "p" + Long.toString(ProcessHandle.current().pid());
80+
try (DatagramSocket socket = new DatagramSocket()) {
81+
socket.setBroadcast(true);
82+
83+
String pid = "p" + ProcessHandle.current().pid();
8184
byte[] data = pid.getBytes();
82-
DatagramSocket socket = new DatagramSocket();
83-
DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName(host), port);
84-
socket.send(packet);
85-
socket.close();
85+
86+
DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName("127.0.0.255"), port);
87+
socket.send(packet);
8688
} catch (IOException e) {
8789
e.printStackTrace();
8890
}
@@ -97,36 +99,37 @@ public class ProcessHeartbeat {
9799
```c
98100
#include <stdio.h>
99101
#include <stdlib.h>
100-
#include <unistd.h>
101102
#include <string.h>
102-
#include <arpa/inet.h>
103-
#include <sys/types.h>
104103
#include <sys/socket.h>
104+
#include <netinet/in.h>
105+
#include <arpa/inet.h>
106+
#include <unistd.h>
105107

106108
void sendPIDOverUDP(int port) {
107109
int sockfd;
108-
struct sockaddr_in servaddr;
109-
char buffer[1024];
110-
snprintf(buffer, sizeof(buffer), "p%d", getpid());
111-
112-
// Creating socket file descriptor
113-
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
110+
struct sockaddr_in addr;
111+
socklen_t addr_len = sizeof(addr);
112+
113+
// Get the current process ID
114+
pid_t pid = getpid();
115+
char pid_str[20];
116+
sprintf(pid_str, "p%d", pid);
117+
118+
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
119+
if (sockfd < 0) {
114120
perror("socket creation failed");
115121
exit(EXIT_FAILURE);
116122
}
117-
118-
memset(&servaddr, 0, sizeof(servaddr));
119-
120-
// Filling server information
121-
servaddr.sin_family = AF_INET;
122-
servaddr.sin_port = htons(port);
123-
servaddr.sin_addr.s_addr = INADDR_BROADCAST;
124-
125-
// Send the PID message
126-
if (sendto(sockfd, buffer, strlen(buffer), 0, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
123+
124+
memset(&addr, 0, addr_len);
125+
addr.sin_family = AF_INET;
126+
addr.sin_port = htons(port);
127+
addr.sin_addr.s_addr = inet_addr("127.0.0.255");
128+
129+
if (sendto(sockfd, pid_str, strlen(pid_str), 0, (struct sockaddr *)&addr, addr_len) < 0) {
127130
perror("sendto failed");
128131
}
129-
132+
130133
close(sockfd);
131134
}
132135
```
@@ -137,36 +140,39 @@ void sendPIDOverUDP(int port) {
137140
### C++
138141
```cpp
139142
#include <iostream>
140-
#include <unistd.h>
141143
#include <string>
142144
#include <cstring>
143-
#include <arpa/inet.h>
144-
#include <sys/types.h>
145145
#include <sys/socket.h>
146+
#include <netinet/in.h>
147+
#include <arpa/inet.h>
148+
#include <unistd.h>
149+
#include <cstdlib>
146150
147151
void sendPIDOverUDP(int port) {
148152
int sockfd;
149-
struct sockaddr_in servaddr;
150-
std::string pid_message = "p" + std::to_string(getpid());
151-
152-
// Creating socket file descriptor
153-
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
153+
struct sockaddr_in addr;
154+
socklen_t addr_len = sizeof(addr);
155+
156+
// Get the current process ID
157+
pid_t pid = getpid();
158+
std::string pid_str = "p" + std::to_string(pid);
159+
const char* pid_data = pid_str.c_str();
160+
161+
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
162+
if (sockfd < 0) {
154163
perror("socket creation failed");
155164
exit(EXIT_FAILURE);
156165
}
157-
158-
memset(&servaddr, 0, sizeof(servaddr));
159-
160-
// Filling server information
161-
servaddr.sin_family = AF_INET;
162-
servaddr.sin_port = htons(port);
163-
servaddr.sin_addr.s_addr = INADDR_BROADCAST;
164-
165-
// Send the PID message
166-
if (sendto(sockfd, pid_message.c_str(), pid_message.length(), 0, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
166+
167+
memset(&addr, 0, addr_len);
168+
addr.sin_family = AF_INET;
169+
addr.sin_port = htons(port);
170+
addr.sin_addr.s_addr = inet_addr("127.0.0.255");
171+
172+
if (sendto(sockfd, pid_data, strlen(pid_data), 0, (struct sockaddr *)&addr, addr_len) < 0) {
167173
perror("sendto failed");
168174
}
169-
175+
170176
close(sockfd);
171177
}
172178
```
@@ -176,16 +182,24 @@ void sendPIDOverUDP(int port) {
176182

177183
### Qt (C++)
178184
```cpp
179-
#include <QUdpSocket>
180185
#include <QCoreApplication>
186+
#include <QUdpSocket>
187+
#include <QHostAddress>
188+
#include <QByteArray>
181189
#include <QProcess>
182190

183-
void sendPIDOverUDP(int port) {
184-
QUdpSocket udpSocket;
185-
QString message = "p" + QString::number(QCoreApplication::applicationPid());
186-
QByteArray data = message.toUtf8();
191+
void sendPIDOverUDP(int port)
192+
{
193+
QString host = "127.0.0.255";
194+
QString pid = "p" + QString::number(QCoreApplication::applicationPid());
195+
QByteArray data = pid.toUtf8();
187196

188-
udpSocket.writeDatagram(data, QHostAddress::Broadcast, port);
197+
QUdpSocket socket;
198+
socket.bind(QHostAddress::AnyIPv4, port, QUdpSocket::ShareAddress);
199+
200+
socket.writeDatagram(data, QHostAddress(host), port);
201+
202+
socket.close();
189203
}
190204
```
191205
</details>
@@ -197,26 +211,27 @@ void sendPIDOverUDP(int port) {
197211
using System;
198212
using System.Net;
199213
using System.Net.Sockets;
200-
using System.Text;
201-
using System.Diagnostics;
202214
203215
public class Program
204216
{
205217
public static void SendPIDOverUDP(int port)
206218
{
207-
UdpClient udpClient = new UdpClient();
208-
int pid = Process.GetCurrentProcess().Id;
209-
string message = "p" + pid.ToString();
210-
byte[] data = Encoding.UTF8.GetBytes(message);
211-
212-
IPEndPoint endPoint = new IPEndPoint(IPAddress.Broadcast, port);
213-
udpClient.Send(data, data.Length, endPoint);
214-
udpClient.Close();
215-
}
216-
217-
public static void Main()
218-
{
219-
SendPIDOverUDP(12345);
219+
try
220+
{
221+
string host = "127.0.0.255";
222+
string pid = "p" + System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
223+
byte[] data = System.Text.Encoding.ASCII.GetBytes(pid);
224+
225+
using (UdpClient client = new UdpClient())
226+
{
227+
client.EnableBroadcast = true;
228+
client.Send(data, data.Length, new IPEndPoint(IPAddress.Parse(host), port));
229+
}
230+
}
231+
catch (Exception e)
232+
{
233+
Console.WriteLine("Exception: " + e.Message);
234+
}
220235
}
221236
}
222237
```
@@ -226,13 +241,22 @@ public class Program
226241

227242
### Python
228243
```python
229-
import os
230244
import socket
245+
import os
231246

232-
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
233-
pid = str(os.getpid())
234-
data = 'p' + pid
235-
sock.sendto(data.encode('utf-8'), ('localhost', 12345))
247+
def send_pid_over_udp(port):
248+
try:
249+
host = '127.0.0.255'
250+
pid = f"p{os.getpid()}"
251+
data = pid.encode()
252+
253+
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
254+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
255+
sock.sendto(data, (host, port))
256+
sock.close()
257+
258+
except Exception as e:
259+
print(f"Exception: {e}")
236260
```
237261
</details>
238262
<details>
@@ -242,13 +266,13 @@ sock.sendto(data.encode('utf-8'), ('localhost', 12345))
242266
```bash
243267
#!/bin/bash
244268

245-
sendPIDOverUDP() {
269+
send_pid_over_udp() {
246270
local port=$1
247-
local pid="p$$"
248-
echo -n $pid | nc -u -w1 -b 127.0.0.1 $port
249-
}
271+
local host="127.0.0.255"
272+
local pid="p$$" # $$ gives the PID of the current shell process
250273

251-
sendPIDOverUDP 12345
274+
echo -n "$pid" | socat - UDP-DATAGRAM:$host:$port,broadcast
275+
}
252276
```
253277
</details>
254278

@@ -311,12 +335,16 @@ Or just `./run.sh &` which is recommended.
311335

312336
## TODO
313337
- Redesign the apps.c
314-
- Replace ini with json file
315338
- Add CPU & RAM usage to the statistics
316-
- Add Telnet console
317-
- Enable remote syslog server reporting
339+
- Create easy-to-use heartbeat libraries
318340
- Enable commands over UDP
341+
- Enable remote syslog server reporting
342+
- Add periodic reboot feature
319343
- Add IPC and TCP support
344+
- Add json support
345+
- Add remote Telnet console
346+
- Add config wizard
347+
- Add multiplatform GUI
320348

321349
## :snowman: Author
322350
Eray Öztürk ([@diffstorm](https://github.com/diffstorm))

0 commit comments

Comments
 (0)