Linux Service Operations
This page is a quick operational reference for Linux service management and server maintenance. We cover systemd and systemctl, service creation and removal, Nginx site cleanup, PID checks, journalctl, Docker logs, cron, and cron versus Celery.
Overview
Section titled “Overview”- Use systemctl to control systemd-managed services.
- Use daemon-reload after creating, editing, or deleting systemd unit files.
- Use restart for app services after code or environment changes.
- Use nginx -t and systemctl reload nginx after Nginx config changes.
- Use journalctl for systemd service logs.
- Use docker compose logs for container application logs.
- Use cron for simple time-based shell commands.
- Use Celery for application background jobs, retries, queues, and scheduled app tasks.
Mental model
Section titled “Mental model”Linux kernel -> systemd -> services -> nginx -> docker -> ssh -> cron or cronie -> custom app services
systemctl -> command tool used to control systemd
journalctl -> command tool used to read logs collected by systemd-journald- systemd is the service manager daemon.
- systemctl is the command-line control tool.
- journalctl is the command-line log reader.
- Nginx, Docker, cron, and custom apps can all run as services managed by systemd.
Check PID 1
Section titled “Check PID 1”PID 1 is usually systemd on modern Arch and Ubuntu systems. It may appear as /sbin/init because that path points to systemd.
ps -p 1 -o pid,comm,argsls -l /sbin/initreadlink -f /sbin/initExample output:
PID COMMAND COMMAND1 systemd /sbin/init
/sbin/init -> ../lib/systemd/systemd/usr/lib/systemd/systemdCommon systemctl commands
Section titled “Common systemctl commands”systemctl status nginxsystemctl status dockersystemctl status my-app.service
sudo systemctl start my-app.servicesudo systemctl stop my-app.servicesudo systemctl restart my-app.service
sudo systemctl enable my-app.servicesudo systemctl disable my-app.service
sudo systemctl daemon-reloadsudo systemctl reset-failed| Command | Use |
|---|---|
| status | Show service state, recent logs, and main process |
| start | Start a stopped service |
| stop | Stop a running service |
| restart | Stop and start the service process |
| reload | Ask a service to re-read its own config if supported |
| enable | Start service automatically on boot |
| disable | Prevent service from starting on boot |
| daemon-reload | Reload systemd unit definitions |
| reset-failed | Clear old failed-state records |
daemon-reload, restart, and reload
Section titled “daemon-reload, restart, and reload”- daemon-reload refreshes systemd unit definitions. It does not restart running services.
- restart restarts the actual service process.
- reload asks a running service to re-read its own config if the service supports reload.
sudo systemctl daemon-reloadsudo systemctl restart my-app.servicesudo systemctl reload nginxUse both daemon-reload and restart after changing a .service file.
sudo nano /etc/systemd/system/my-app.servicesudo systemctl daemon-reloadsudo systemctl restart my-app.servicesudo systemctl status my-app.serviceUse only restart when the app code changed but the .service file did not change.
sudo systemctl restart my-app.servicesudo systemctl status my-app.serviceCreate a systemd service
Section titled “Create a systemd service”Create a service file under /etc/systemd/system for custom application services.
sudo nano /etc/systemd/system/my-app.serviceExample service file:
[Unit] Description=My App Service After=network.target
[Service] WorkingDirectory=/home/ubuntu/my-app ExecStart=/home/ubuntu/my-app/.venv/bin/python app.py Restart=always RestartSec=5 User=ubuntu EnvironmentFile=/home/ubuntu/my-app/.env
[Install] WantedBy=multi-user.targetLoad the new definition, start it, enable it on boot, and inspect status.
sudo systemctl daemon-reloadsudo systemctl start my-app.servicesudo systemctl enable my-app.servicesudo systemctl status my-app.serviceUpdate a systemd service
Section titled “Update a systemd service”If the service file changes, reload systemd definitions and restart the service process.
sudo nano /etc/systemd/system/my-app.servicesudo systemctl daemon-reloadsudo systemctl restart my-app.servicesudo systemctl status my-app.serviceIf only application code changed, restart the service without daemon-reload.
sudo systemctl restart my-app.servicesudo systemctl status my-app.serviceRemove a systemd service
Section titled “Remove a systemd service”Stop the service, disable boot startup, confirm the unit file path, remove the unit file, reload systemd definitions, and clear failed state if needed.
sudo systemctl stop service-name.servicesudo systemctl disable service-name.servicesudo systemctl cat service-name.servicesudo rm /etc/systemd/system/service-name.servicesudo systemctl daemon-reloadsudo systemctl reset-failedsystemctl status service-name.serviceExpected final output:
Unit service-name.service could not be found.Remove multiple custom services
Section titled “Remove multiple custom services”Use one command per phase when removing a group of related services.
sudo systemctl stop app-backend.service app-worker.service app-beat.service app-frontend.service
sudo systemctl disable app-backend.service app-worker.service app-beat.service app-frontend.service
sudo rm /etc/systemd/system/app-backend.servicesudo rm /etc/systemd/system/app-worker.servicesudo rm /etc/systemd/system/app-beat.servicesudo rm /etc/systemd/system/app-frontend.service
sudo systemctl daemon-reloadsudo systemctl reset-failedConfirm no matching units remain.
systemctl list-unit-files | grep appsystemctl list-units --all | grep appNginx as a systemd service
Section titled “Nginx as a systemd service”- Nginx is installed server software.
- nginx.service is the systemd service that runs Nginx.
- systemctl manages the Nginx service lifecycle.
- Nginx usually acts as the public entry point for web traffic.
sudo systemctl status nginxsudo systemctl start nginxsudo systemctl stop nginxsudo systemctl restart nginxsudo systemctl reload nginxsudo systemctl enable nginxsudo systemctl disable nginx
systemctl cat nginxNginx config locations
Section titled “Nginx config locations”/etc/nginx/nginx.conf/etc/nginx/sites-available//etc/nginx/sites-enabled/- sites-available stores site config files.
- sites-enabled stores symlinks to active site configs.
- A file in sites-available is inactive unless it is linked from sites-enabled.
ls /etc/nginx/sites-availablels -l /etc/nginx/sites-enabledRemove an Nginx site config
Section titled “Remove an Nginx site config”Remove the enabled symlink first, then remove the available config file. Test before reloading Nginx.
ls -l /etc/nginx/sites-enabled | grep example-site
sudo rm -f /etc/nginx/sites-enabled/example-site.confsudo rm -f /etc/nginx/sites-available/example-site.conf
sudo nginx -tsudo systemctl reload nginxExpected nginx -t output:
nginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successfulDefault Nginx site
Section titled “Default Nginx site”- The default file can stay in sites-available as a reference.
- It is inactive if it is not linked from sites-enabled.
- Remove only the sites-enabled/default symlink if the default site is active and not needed.
ls -l /etc/nginx/sites-enabled
sudo rm -f /etc/nginx/sites-enabled/defaultsudo nginx -tsudo systemctl reload nginxWhy Nginx is used in production
Section titled “Why Nginx is used in production”In development, apps are often accessed directly on localhost ports. In production, users usually access Nginx on ports 80 and 443, then Nginx forwards traffic to internal app ports.
Development:
Browser -> http://localhost:3000 -> http://localhost:8000
Production:
Browser -> https://example.com -> Nginx on port 443 -> frontend app on localhost or Docker -> backend app on localhost or Docker- Nginx handles public ports 80 and 443.
- Nginx can handle HTTPS certificates.
- Nginx routes domains and paths to the correct app.
- Nginx keeps app ports hidden from the public internet.
- Nginx can reload config without fully restarting the service.
AWS ALB and Nginx
Section titled “AWS ALB and Nginx”- AWS Application Load Balancer can replace Nginx as the public reverse proxy in many AWS-native setups.
- ALB is useful with multiple EC2 instances, ECS services, target groups, health checks, and autoscaling.
- Nginx is often simpler for a single EC2 instance.
Single EC2 pattern:
Browser -> Nginx on EC2 -> app services or Docker containers
AWS ALB pattern:
Browser -> AWS Application Load Balancer -> EC2 instance -> ECS task -> target groupProcess and PID inspection
Section titled “Process and PID inspection”ps auxps -p 1 -o pid,comm,args
ps aux | grep nginxps aux | grep dockerps aux | grep node
ps aux | grep '[n]ginx'
pgrep nginxpgrep -a nginx
pstree -p
tophtopInstall helper tools on Arch if needed.
sudo pacman -S psmisc htopKernel threads in ps output
Section titled “Kernel threads in ps output”Processes shown inside square brackets are usually kernel threads, not normal user services.
root 1 0.0 0.0 26452 15516 ? Ss Apr30 0:03 /sbin/initroot 2 0.0 0.0 0 0 ? S Apr30 0:00 [kthreadd]root 3 0.0 0.0 0 0 ? S Apr30 0:00 [pool_workqueue]root 15 0.0 0.0 0 0 ? S Apr30 0:01 [ksoftirqd/0]- PID 1 is usually systemd or /sbin/init.
- PID 2 is kthreadd, the kernel thread manager.
- kworker entries are kernel worker threads.
- ksoftirqd entries are kernel interrupt handling workers.
Check listening ports
Section titled “Check listening ports”Use ss to see which processes listen on ports. Add sudo to see process names clearly.
ss -ltnpsudo ss -ltnp
sudo ss -ltnp | grep 3000sudo ss -ltnp | grep 8000sudo ss -ltnp | grep 80sudo ss -ltnp | grep 443journalctl and systemd-journald
Section titled “journalctl and systemd-journald”- systemd-journald is the background log collection daemon.
- journalctl is the command used to read logs.
- Use journalctl for services managed directly by systemd.
journalctl -u nginxjournalctl -u dockerjournalctl -u my-app.service
journalctl -u my-app.service -fjournalctl -u my-app.service -n 100journalctl -u my-app.service --since "1 hour ago"journalctl -u my-app.service --since today
journalctl -bjournalctl -u my-app.service -bCheck journald itself:
systemctl status systemd-journaldps aux | grep '[s]ystemd-journald'Docker logs and journal logs
Section titled “Docker logs and journal logs”- journalctl -u docker shows Docker daemon logs.
- docker compose logs shows logs from application containers.
- Use Docker logs for app exceptions inside containers.
- Use journalctl -u docker for Docker engine, network, image, and daemon problems.
systemd -> docker.service -> Docker daemon -> containers -> backend app -> frontend appjournalctl -u docker -f
docker compose logs -f backenddocker compose logs -f frontend
docker compose logs --tail=100 backenddocker compose logs --tail=100 frontendCron and cronie
Section titled “Cron and cronie”- cron is a time-based command scheduler.
- cronie is a common cron implementation on Arch.
- crontab edits the current user’s scheduled jobs.
- Cron uses the system’s local timezone by default.
sudo pacman -S croniesudo systemctl enable --now croniesystemctl status cronie
crontab -ecrontab -lUse nano if vi is missing.
EDITOR=nano crontab -e
echo 'export EDITOR=nano' >> ~/.bashrcsource ~/.bashrcCron time format
Section titled “Cron time format”minute hour day-of-month month day-of-week commandExample: run a Python script every day at 03:00.
0 3 * * * /home/example/project/.venv/bin/python /home/example/project/scripts/daily_job.pyCheck local system time and timezone.
datetimedatectltimedatectl | grep "Time zone"Set timezone if needed.
sudo timedatectl set-timezone Europe/IstanbulCron logging pattern
Section titled “Cron logging pattern”Redirect command output to a log file when running scripts from cron. This keeps print output and errors easy to inspect.
mkdir -p /home/example/project/logs0 3 * * * cd /home/example/project && /home/example/project/.venv/bin/python scripts/daily_job.py >> logs/daily_job.log 2>&1-
appends normal output to the log file.
- 2>&1 sends error output to the same log file.
tail -f /home/example/project/logs/daily_job.log
journalctl -u cronie --since todayCron versus Celery
Section titled “Cron versus Celery”| Use case | Better tool |
|---|---|
| Run one Python script every day | cron |
| Run backup or cleanup commands | cron |
| Send verification email after user registration | Celery |
| Process uploads or reports in the background | Celery |
| Retry failed external API work | Celery |
| Schedule app-level tasks with workers | Celery beat |
cron At this time, run this shell command.
Celery Put this app task into a background queue.
Celery beat At this time, put this app task into the Celery queue.
Redis Broker where Celery tasks wait.
Celery worker Process that consumes queued tasks.For web apps, slow or retryable work should usually move out of the request and into a background worker.
User registers -> backend creates user -> backend queues send_verification_email task -> backend returns response quickly
Celery worker -> sends email separately -> retries if neededQuick service cleanup checklist
Section titled “Quick service cleanup checklist”sudo systemctl stop example.servicesudo systemctl disable example.servicesudo systemctl cat example.servicesudo rm /etc/systemd/system/example.servicesudo systemctl daemon-reloadsudo systemctl reset-failedsystemctl status example.serviceExpected final output:
Unit example.service could not be found.Quick Nginx cleanup checklist
Section titled “Quick Nginx cleanup checklist”ls -l /etc/nginx/sites-enabled | grep example
sudo rm -f /etc/nginx/sites-enabled/example.confsudo rm -f /etc/nginx/sites-available/example.conf
sudo nginx -tsudo systemctl reload nginx
ls /etc/nginx/sites-availablels -l /etc/nginx/sites-enabledDebug command set
Section titled “Debug command set”systemctl status nginxsystemctl status dockersystemctl list-unit-files | grep examplesystemctl list-units --all | grep example
journalctl -u nginx -n 100journalctl -u docker -n 100
docker compose logs --tail=100 backenddocker compose logs --tail=100 frontend
ps -p 1 -o pid,comm,argsps aux | grep '[n]ginx'pgrep -a nginx
sudo ss -ltnpsudo ss -ltnp | grep 8000Reference paths
Section titled “Reference paths”- Custom systemd units: /etc/systemd/system/
- Packaged systemd units on Arch: /usr/lib/systemd/system/
- Nginx main config: /etc/nginx/nginx.conf
- Nginx available sites: /etc/nginx/sites-available/
- Nginx enabled sites: /etc/nginx/sites-enabled/
- User crontab editor: crontab -e
- Docker Compose logs: docker compose logs
- Systemd service logs: journalctl -u service-name