Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup script not running on exit when running the script as a systemd service #67

Open
ghost opened this issue Oct 22, 2022 · 5 comments

Comments

@ghost
Copy link

ghost commented Oct 22, 2022

try: at line 1588 breaks early because of #67 (comment) and not even finally: will run for some reason

Maybe systemd is killing the process early so the script can't find it and it won't execute the rest of the code?

try:
with open(cleanup_filename, "w") as fp:
fp.write("#!/bin/sh\n")
for rule in load_rules(port, definitions):
iptables_cmd = f"iptables -t nat -I PREROUTING {rule}"
logging.info(f"Running: {iptables_cmd}")
if os.system(iptables_cmd):
raise RootRequiredError
applied_rules.append(rule)
fp.write(f"iptables -t nat -D PREROUTING {rule}\n")
os.chmod(cleanup_filename, 0o777)
os.system("sysctl -w net.ipv4.ip_forward=1")
listener.listen(8)
logging.info(f"Listening on {listener.getsockname()}...")
logging.info("Press Ctrl+C to quit.")
child_pids = set()
def on_child_exit(signum, frame):
if child_pids:
pid, status = os.waitpid(-1, os.WNOHANG)
if pid:
logging.info(f"[{pid:<6}] has exit with status code {status}.")
child_pids.discard(pid)
signal.signal(signal.SIGCHLD, on_child_exit)
while True:
for child_pid in child_pids:
try:
os.kill(child_pid, 0)
except OSError:
child_pids.remove(child_pid)
try:
sock, source = listener.accept()
except KeyboardInterrupt:
break
child_pid = os.fork()
if child_pid == 0:
is_child = True
child_pids.clear()
listener.close()
return Connection(sock, source, definitions, args).run()
sock.close()
child_pids.add(child_pid)
for child_pid in child_pids:
try:
os.kill(child_pid, signal.SIGINT)
except OSError:
pass
except RootRequiredError:
logging.error("This program requires root permissions.\n")
err = True
finally:
if not is_child:
logging.info("Cleaning up...")
for rule in applied_rules:
iptables_cmd = f"iptables -t nat -D PREROUTING {rule}"
logging.info(f"Running: {iptables_cmd}")
exit_code = os.system(iptables_cmd)
if exit_code:
logging.warning(f"\t=> Failed with exit code {exit_code}")
err = True
os.remove(cleanup_filename)
if err:
logging.error("One or more error have occurred during cleanup.")
return -1
else:
logging.info("Cleanup complete.")
return 0

@ghost
Copy link
Author

ghost commented Oct 22, 2022

While playing around with logging.info() I noticed the while loop breaks at sock, source = listener.accept() and everything below that and outside of the loop won't be executed. Even the finally: at the very bottom won't be executed at all

while True:
for child_pid in child_pids:
try:
os.kill(child_pid, 0)
except OSError:
child_pids.remove(child_pid)
try:
sock, source = listener.accept()
except KeyboardInterrupt:
break
child_pid = os.fork()
if child_pid == 0:
is_child = True
child_pids.clear()
listener.close()
return Connection(sock, source, definitions, args).run()
sock.close()
child_pids.add(child_pid)

@ayyaruq
Copy link
Contributor

ayyaruq commented Oct 24, 2022

Why not just add the cleanup script to the ExecStopPost option in your unit file? Might be worth the unit separating out the components too but that'll get weird.

@ghost
Copy link
Author

ghost commented Oct 24, 2022

That's what I did for now as a workaround but the problem yet remains

[Unit]
Description=XivAlexander script

[Service]
Type=simple
User=root
WorkingDirectory=/root/xivalexander
#ExecStart=/bin/bash run.sh
ExecStart=/usr/bin/python3 mitigate.py
ExecStop=-/bin/bash .cleanup.sh
ExecStop=-/bin/rm .cleanup.sh

[Install]
WantedBy=multi-user.target

@ayyaruq
Copy link
Contributor

ayyaruq commented Oct 30, 2022

Ah I follow now, should maybe just make cleanup callable as a param, or write the iptables rules to some file that can be consumed by cleanup independent of the in-memory ports and crap.

I keep the cleanup script around for manual use, so it works just fine in systemd (except I don't use systemd), mostly since using fixed ports. Could be worth it for you, just add a flag and set port to it, env var it, or hardcode if you need. Probably a good PR to make port configurable.

@xzn
Copy link

xzn commented Jan 14, 2023

Try this:

[Unit]
Description=XivAlexander script

[Service]
Type=simple
User=root
WorkingDirectory=/root
ExecStart=/bin/bash run.sh
Restart=on-failure
RestartSec=5
KillSignal=SIGINT

[Install]
WantedBy=multi-user.target

(Added KillSignal=SIGINT line to [Service])

#!/bin/bash
curl https://raw.githubusercontent.com/Soreepeong/XivMitmLatencyMitigator/main/mitigate.py | exec python3

(Added exec to python3)

It makes it so that sigint (ctrl+c) is passed to the mitigate.py script

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants