Используйте ln
для создания символических ( -s
) ссылок, которые позволяют использовать несколько указателей на один и тот же фактический файл. ответьте на ваш главный вопрос. Однако ваш пример использования автоматического добавления теперь соответствует этому (но это может быть полезно для других, читающих ваш заголовок и заголовок).
ln -s src/of/actual/file merge_directory/pointer_link
После просмотра руководства еще несколько раз (да, ответ никогда не находится с первого раза...), я нашел решение... которое не сработало. После еще большего просмотра я, наконец, нашел самое элегантное решение из всех возможных.
[Unit]
Description=Minecraft server
After=local-fs.target network.target
[Service]
WorkingDirectory=/home/minecraft/minecraft_server
User=minecraft
Group=minecraft
Type=forking
# Run it as a non-root user in a specific directory
ExecStart=/usr/bin/screen -h 1024 -dmS minecraft ./minecraft_server.sh
# I like to keep my commandline to launch it in a separate file
# because sometimes I want to change it or launch it manually
# If it's in the WorkingDirectory, then we can use a relative path
# Send "stop" to the Minecraft server console
ExecStop=/usr/bin/screen -p 0 -S minecraft -X eval 'stuff \"stop\"\015'
# Wait for the PID to die - otherwise it's killed after this command finishes!
ExecStop=/bin/bash -c "while ps -p $MAINPID > /dev/null; do /bin/sleep 1; done"
# Note that absolute paths for all executables are required!
[Install]
WantedBy=multi-user.target
Это действительно выглядит лучше, чем мой первоначальный сценарий! Однако есть несколько регрессий.
systemctl start minecraft
или systemctl stop minecraft
, обязательно проверьте systemctl status minecraft
, потому что эти команды не дают никакого вывода, даже если они действительно не работают. Это единственная серьезная регрессия по сравнению со скриптами - "всегда проверяйте вывод" является правилом №1 в IT, но systemd, похоже, не заботится об этом... Я использую этот служебный файл:
[Unit]
Description=Minecraft server
Wants=network.target
After=network.target
[Service]
User=minecraft
Group=minecraft
Nice=5
WorkingDirectory=/home/minecraft/.minecraft/
KillMode=process
KillSignal=SIGINT
SuccessExitStatus=130
ExecStart=/usr/bin/java -Xms1G -Xmx1G -jar /home/minecraft/.minecraft/minecraft_server.jar nogui
[Install]
WantedBy=multi-user.target
Я использую SIGINT (ctrl + c) для его остановки:
KillSignal=SIGINT
и SuccessExitStatus для успешного завершения:
SuccessExitStatus=130
tl;dr :Не использовать screen вообще. Используйте RCON для управления сервером.
Я понимаю, что экран всегда был стандартом де-факто для управления серверами Minecraft, но, попробовав оба способа, я пришел к выводу, что RCON решает проблему управления гораздо чище.
Причина запуска сервера в сеансе экрана заключается в том, что вы можете отправлять команды на сервер, вставляя их в его стандартный ввод с помощью сеанса экрана. Вы также можете подключиться непосредственно к сеансу экрана, чтобы использовать интерактивную консоль сервера. Это важные функции, но экран — не единственный способ их реализации.
Minecraft поддерживает протокол RCON для удаленного администрирования. Вы можете использовать его локально для взаимодействия с сервером. Я использую инструмент командной строки mcrcon , который работает либо для отправки отдельных команд, либо в качестве интерактивного терминала. Это более мощно, чем экран, и, возможно, менее хакерское (отправка команд через eval
и stuff
всегда заставляла меня морщиться ).
Мой minecraft.service
файл выглядит так:
Description=Minecraft Server
After=network.target
[Service]
Type=simple
User=minecraft
Group=minecraft
WorkingDirectory=/srv/minecraft
ExecStart=/usr/local/bin/minecraft/start
ExecStop=/usr/local/bin/minecraft/stop
Restart=always
[Install]
WantedBy=default.target
Сценарий start
просто запускает исполняемый файл сервера:
#!/bin/sh
cd /srv/minecraft
java -Xmx12G -Xms12G \
-XX:+UnlockExperimentalVMOptions \
-XX:+UseG1GC \
-XX:G1NewSizePercent=50 \
-XX:MaxGCPauseMillis=50 \
-XX:+AlwaysPreTouch \
-jar server.jar nogui
Скрипт stop
отправляет команду на сервер и ожидает остановки процесса:
#!/bin/sh
/usr/local/bin/minecraft/rcon stop
while kill -0 $MAINPID 2>/dev/null
do
sleep 0.5
done
Сценарий rcon
— это просто сокращение:
#!/bin/sh
mcrcon -H localhost -P 25575 -p "password omitted" $@
В моем сценарии порт RCON и пароль жестко закодированы, но вы можете легко получить их из файла server.properties
. Кроме того, mcrcon
будет принимать их через переменные среды, а не через параметры командной строки, если вы предпочитаете.
Другие примечания:
server.properties
, но вы можете оставить порт закрытым в брандмауэре, чтобы предотвратить его удаленное использование. rcon
без аргументов (или вызовите mcrcon напрямую ).