Skip to content

Instantly share code, notes, and snippets.

@claudio4
Last active October 10, 2022 22:22
Show Gist options
  • Save claudio4/54f1ffa7b709b00f6503c02d325b2003 to your computer and use it in GitHub Desktop.
Save claudio4/54f1ffa7b709b00f6503c02d325b2003 to your computer and use it in GitHub Desktop.
[Unit]
Description=Minecraft server: %i
Wants=network.target
After=local-fs.target network.target
[Service]
User=minecraft
Group=minecraft
EnvironmentFile=/etc/conf.d/mc-%i
KillMode=process
KillSignal=SIGINT
TimeoutStopSec=300
NoNewPrivileges=true
PrivateDevices=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=full
WorkingDirectory=/opt/minecraft/%i
ExecStart=/opt/minecraft/.local/bin/MinecraftSystemdWrapper /usr/bin/java $ARGS -jar server.jar
#ExecStop=/usr/local/bin/mcrcon -H localhost -P ${RCON_PORT} -p ${RCON_PASSWD} stop
[Install]
WantedBy=multi-user.target
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int fd[2];
pid_t pid;
void signal_handler(int sig) {
fprintf(stderr, "Signal %s received, stoping the server\n", strsignal(sig));
int againCounter = 0;
SEND_STOP:
if (write(fd[1], "stop\n", 5) != -1) {
return;
}
// if EAGAIN silently retry 5 times more
if (errno == EAGAIN) {
if (againCounter < 6) {
againCounter++;
goto SEND_STOP;
} else {
fprintf(
stderr,
"Error sending the stop command to the server: Too many retries\n");
}
} else {
fprintf(stderr, "Error sending the stop command to the server: %s\n",
strerror(errno));
}
if (kill(pid, SIGINT) == -1) {
fprintf(stderr, "Error killing the server: %s\n", strerror(errno));
}
}
int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "No command provided\n");
return 2;
}
// create pipes to communicate with the sever process
if (pipe(fd) == -1) {
fprintf(stderr, "Error creating the pipes\n");
return 1;
}
pid = fork();
if (pid == -1) {
fprintf(stderr, "Error creating the child process\n");
return 1;
} else if (pid == 0) {
// set pipe as stdin
close(fd[1]);
dup2(fd[0], STDIN_FILENO);
// create own process group (more info in https://nth.sh/Z9vj)
if (setsid() == -1) {
fprintf(stderr, "Error creating new process group: %s\n",
strerror(errno));
return 22;
}
execvp(argv[1], &argv[1]);
// this code should be replaced by the exec, if this coded is reached that
// means that exec call failed
perror("error executing the program");
return 1;
}
close(fd[0]);
// se-up signal handlers
signal(SIGHUP, signal_handler);
signal(SIGINT, signal_handler);
signal(SIGQUIT, signal_handler);
signal(SIGTERM, signal_handler);
// wait for the sever to stop and replicate exit code
int status;
waitpid(pid, &status, 0);
if ((status = WEXITSTATUS(status)) != 0) {
return status;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment