Difference between revisions of "EBC Exercise 21b systemd"

From eLinux.org
Jump to: navigation, search
m (Autostart at boot time)
m (Running your own service)
Line 120: Line 120:
  
 
== Running your own service ==
 
== Running your own service ==
If you check in '''exercises/realtime''' you find '''boneServer.js''' a server for some demos. You run it with:
+
If you check in '''exercises/flask/server''' you find '''app4.py''' a server for some flask demos. You run it with:
  beagle$ '''cd exercises/realtime'''
+
  beagle$ '''cd exercises/flask/server'''
  beagle$ '''./boneServer.js'''
+
  beagle$ '''./app4.py'''
Listening on 8080
+
  * Serving Flask app "app4" (lazy loading)
    info  - socket.io started
+
  * Environment: production
Now point a browser to 192.168.7.2:8080.  You'll see a list of demos served up by '''boneServer.js'''.  Suppose you want the boneServer to automatically start every time the the Beagle boots.  Here is how to do it.
+
    WARNING: This is a development server. Do not use it in a production deployment.
 +
    Use a production WSGI server instead.
 +
  * Debug mode: on
 +
  * Running on http://0.0.0.0:8081/ (Press CTRL+C to quit)
 +
  * Restarting with stat
 +
  * Debugger is active!
 +
  * Debugger PIN: 103-331-254
 +
Now point a browser to 192.168.7.2:8081.  You'll see the demo served up by flask.  Suppose you want the '''app4.py''' to automatically start every time the Beagle boots.  Here is how to do it.
  
 
We need to create a service file and the quickest way is to find one that does similar things.
 
We need to create a service file and the quickest way is to find one that does similar things.
  beagle$ '''systemctl | grep bone'''
+
  bone$ '''systemctl | grep nginx'''
bonescript-autorun.service  loaded active running  Bonescript autorun
+
  nginx.service  loaded active running  A high performance web server and a reverse proxy server
bonescript.service          loaded active running  Bonescript server
+
Check its status.
bonescript.socket          loaded active running  bonescript.socket
+
  bone$ '''systemctl status nginx.service'''
I see a couple of bonescript servers that look promising.
+
  ● nginx.service - A high performance web server and a reverse proxy server
  beagle$ '''systemctl status bonescript'''
+
    Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
  bonescript.service - Bonescript server
+
    Active: active (running) since Tue 2023-01-24 10:07:23 EST; 3h 13min ago
          Loaded: loaded (/lib/systemd/system/bonescript.service; static)
+
...
          Active: active (running) since Sun 2000-01-09 15:07:55 EST; 13 years 9 months ago
+
Looks like the file is in '''/lib/systemd/system/nginx.service''' copy it to a handy place and take a look.
        Main PID: 357 (node)
+
beagle$ '''cp /lib/systemd/system/nginx.service flask.service'''
          CGroup: name=systemd:/system/bonescript.service
+
beagle$ '''cat flask. Service'''
          `-357 /usr/bin/node server.js
+
[Unit]
 +
Description=A high performance web server and a reverse proxy server
 +
Documentation=man:nginx(8)
 +
After=network. Target nss-lookup.target
 +
 +
[Service]
 +
Type=forking
 +
PIDFile=/run/nginx.pid
 +
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
 +
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
 +
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
 +
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
 +
TimeoutStopSec=5
 +
KillMode=mixed
 
   
 
   
  Jan 09 15:07:55 yoder-black-bone systemd[1]: Starting Bonescript server...
+
  [Install]
Jan 09 15:08:04 yoder-black-bone bonescript[357]: [35B blob data]
+
  WantedBy=multi-user. Target
  Jan 09 15:08:05 yoder-black-bone bonescript[357]: - - - [Sun, 09 Jan 2000 20:...
+
Modify the file so it will work for your server. Make sure to modify 'Description' as well or your service will confuse itself with the original nginx.service. Here's what mine looks like:
Looks like the file is in '''/lib/systemd/system/bonescript.service''' copy it to a handy place and take a look.
 
beagle$ '''cp /lib/systemd/system/bonescript.service boneServer.service'''
 
beagle$ '''cat boneServer.service'''
 
 
  [Unit]
 
  [Unit]
  Description=Bonescript server
+
  Description=flask server  
 
   
 
   
 
  [Service]
 
  [Service]
  WorkingDirectory=/usr/lib/node_modules/bonescript
+
  WorkingDirectory=/home/debian/exercises/flask/server
  ExecStart=/usr/bin/node server.js
+
  ExecStart=/home/debian/exercises/flask/server/app4.py
  SyslogIdentifier=bonescript
+
  SyslogIdentifier=flask
 
   
 
   
  '''[Install]'''
+
  [Install]
  '''WantedBy=multi-user.target'''
+
  WantedBy=multi-user. Target
I copied the last two line from /lib/systemd/system/cloud9.service since they are needed to start at boot time.  Modify the file so it will work for your server. Make sure to modify 'Description' as well or your service will confuse itself with the original bonescript.service.
 
 
 
There is one other thing you have to add to the file.  When node.js runs it needs to know where to find its modules. There is an environment variable that says where
 
beagle$ '''echo $NODE_PATH'''
 
/usr/lib/node_modules
 
You need to add a line to the service file that set this environment variable. Look at the other files in /lib/systemd/system to see how this is done.  (Hint:  '''grep Env *''').
 
  
Once your BoneServer.service file is ready, copy it to the right place
+
Once your flask. Service file is ready, copy it to the right place
  beagle$ '''cp boneServer.service /lib/systemd/system'''
+
  bone$ '''cp flask.service /lib/system/system'''
 
and start the server
 
and start the server
  beagle$ '''systemctl start boneServer'''
+
  beagle$ '''systemctl start flask'''
Point your browser to 192.168.7.2:8080 and see if it works.
+
Point your browser to 192.168.7.2:8081 and see if it works.
  
 
To make it work after rebooting
 
To make it work after rebooting
  beagle$ '''systemctl enable boneServer'''
+
  bone$ '''systemctl enable flask'''
  ln -s '/lib/systemd/system/boneServer.service' '/etc/systemd/system/multi-user.target.wants/boneServer.service'
+
  ln -s '/lib/systemd/system/flask. Service' '/etc/systemd/system/multi-user.target.wants/boneServer.service'
 
Notice it copies your file to another place. Try rebooting and see if it works.
 
Notice it copies your file to another place. Try rebooting and see if it works.
  
 
{{YoderFoot}}
 
{{YoderFoot}}

Revision as of 11:31, 24 January 2023

thumb‎ Embedded Linux Class by Mark A. Yoder


Traditionally user space initialization has been done using init.d, however recently many distributions have been switching to systemd

systemd is a system and service manager for Linux, compatible with SysV and LSB init scripts. systemd provides aggressive parallelization capabilities, uses socket and D-Bus activation for starting services, offers on-demand starting of daemons, keeps track of processes using Linux control groups, supports snapshotting and restoring of the system state, maintains mount and automount points and implements an elaborate transactional dependency-based service control logic.

Here we'll see how to use systemd as an administration and how to create a simple service.

Administration

There are a few simple commands that show what's running under systemd and how to stop and start them. The examples here were inspired by the twenty part series on systemd administration and the three part intro by Carla Schroder

To see what's running, run

bone$ systemctl
 UNIT                                                                    >
 proc-sys-fs-binfmt_misc.automount                                       >
 sys-devices-platform-ocp-44c00000.interconnect-44c00000.interconnect:seg>
 sys-devices-platform-ocp-44c00000.interconnect-44c00000.interconnect:seg>
 sys-devices-platform-ocp-47400000.target\x2dmodule-47401400.usb-musb\x2d>
 sys-devices-platform-ocp-47400000.target\x2dmodule-47401400.usb-musb\x2d>
 sys-devices-platform-ocp-47400000.target\x2dmodule-47401c00.usb-musb\x2d>
 sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg>
 sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg>
 sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg>
 sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg>
 sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg>
 sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg>
 sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg>
 sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg>
 sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg>
 sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg>
 sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg>
 sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg>
 sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg>
 sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg>
 sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg>
 sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg>
 sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg>
 sys-devices-platform-ocp-48000000.interconnect-48000000.interconnect:seg>
 sys-devices-platform-ocp-4a000000.interconnect-4a000000.interconnect:seg>
 sys-devices-virtual-misc-rfkill.device                                  >
 sys-devices-virtual-net-docker0.device                                  >
 sys-devices-virtual-tty-ttyGS0.device                                   >
 sys-module-configfs.device                                              >
 sys-module-fuse.device                                                  >
 sys-subsystem-net-devices-can0.device                                   >
 sys-subsystem-net-devices-can1.device                                   >
 sys-subsystem-net-devices-docker0.device                                >
 sys-subsystem-net-devices-eth0.device                                   >
 sys-subsystem-net-devices-usb0.device                                   >
 sys-subsystem-net-devices-usb1.device                                   >
 sys-subsystem-net-devices-wlan0.device                                  >
 -.mount                                                                 >
 dev-mqueue.mount                                                        >
 run-docker-netns-default.mount                                          >
 run-user-1000.mount                                                     >
 sys-fs-fuse-connections.mount

and so on. Look through the list and see what you recognize. If you make your window bigger you will see more information. Here's how to find more details about a given process.

bone$ systemctl status nginx.service
● nginx.service - A high performance web server and a reverse proxy server
    Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enab>
    Active: active (running) since Wed 2023-01-11 15:25:04 EST; 1 weeks 5 days ago
      Docs: man:nginx(8)
  Main PID: 750 (nginx)
     Tasks: 2 (limit: 1024)
    Memory: 3.7M
       CPU: 2.018s
    CGroup: /system.slice/nginx.service
            ├─750 nginx: master process /usr/sbin/nginx -g daemon on; master_proces>
            └─751 nginx: worker process

Jan 11 15:25:01 ece434 systemd[1]: Starting A high performance web server and a reve>
Jan 11 15:25:04 ece434 systemd[1]: Started A high performance web server and a rever>

Stopping and Starting

You can stop a process with

bone$ sudo systemctl stop nginx.service

Now try accessing the web server (192.168.7.2). It isn't there. You can start it with

bone$ systemctl start nginx.service
bone$ systemctl status nginx.service
● nginx.service - A high performance web server and a reverse proxy server
    Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
    Active: active (running) since Tue 2023-01-24 10:07:23 EST; 38s ago
      Docs: man:nginx(8)
   Process: 16409 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
   Process: 16410 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
  Main PID: 16411 (nginx)
     Tasks: 2 (limit: 1024)
    Memory: 5.7M
       CPU: 392ms
    CGroup: /system.slice/nginx.service
            ├─16411 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
            └─16412 nginx: worker process

Jan 24 10:07:12 ece434 systemd[1]: Starting A high performance web server and a reverse proxy server...
Jan 24 10:07:23 ece434 systemd[1]: Started A high performance web server and a reverse proxy server.

Notice the log messages have changed.

Now, when you browse to 192.168.7.2 you will get an answer.

Autostart at boot time

You can use enable and disable to make a service start (or not start) at boot time.

bone$ sudo systemctl disable nginx.service
Synchronizing state of nginx.service with SysV service script with /lib/systemd/system-sysv-install.
Executing: /lib/system/systemd-sysv-install disable nginx
Removed /etc/system/system/multi-user.target.wants/nginx.service.
bone$ sudo systemctl enable nginx.service
Synchronizing state of nginx.service with SysV service script with /lib/systemd/system-sysv-install.
Executing: /lib/system/systemd-sysv-install enable nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /lib/systemd/system/nginx.service.

Watch out though, if some other service needs the service you disabled, it will start anyway.

Stopping no matter what

If you want to stop a service NO MATTER WHAT.

beagle$ ln -s /dev/null /etc/systemd/system/servicename.service
beagle$ systemctl daemon-reload

systemd first looks in /etc/systemd/system and then looks in /lib/systemd/system. The command above places an empty file in /etc/systemd/system, so the real file in /lib/systemd/system is never seen.

Running your own service

If you check in exercises/flask/server you find app4.py a server for some flask demos. You run it with:

beagle$ cd exercises/flask/server
beagle$ ./app4.py
 * Serving Flask app "app4" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://0.0.0.0:8081/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 103-331-254

Now point a browser to 192.168.7.2:8081. You'll see the demo served up by flask. Suppose you want the app4.py to automatically start every time the Beagle boots. Here is how to do it.

We need to create a service file and the quickest way is to find one that does similar things.

bone$ systemctl | grep nginx
 nginx.service  loaded active running   A high performance web server and a reverse proxy server

Check its status.

bone$ systemctl status nginx.service
● nginx.service - A high performance web server and a reverse proxy server
    Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
    Active: active (running) since Tue 2023-01-24 10:07:23 EST; 3h 13min ago
...

Looks like the file is in /lib/systemd/system/nginx.service copy it to a handy place and take a look.

beagle$ cp /lib/systemd/system/nginx.service flask.service
beagle$ cat flask. Service
[Unit]
Description=A high performance web server and a reverse proxy server
Documentation=man:nginx(8)
After=network. Target nss-lookup.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed

[Install]
WantedBy=multi-user. Target

Modify the file so it will work for your server. Make sure to modify 'Description' as well or your service will confuse itself with the original nginx.service. Here's what mine looks like:

[Unit]
Description=flask server 

[Service]
WorkingDirectory=/home/debian/exercises/flask/server
ExecStart=/home/debian/exercises/flask/server/app4.py
SyslogIdentifier=flask

[Install]
WantedBy=multi-user. Target

Once your flask. Service file is ready, copy it to the right place

bone$ cp flask.service /lib/system/system

and start the server

beagle$ systemctl start flask

Point your browser to 192.168.7.2:8081 and see if it works.

To make it work after rebooting

bone$ systemctl enable flask
ln -s '/lib/systemd/system/flask. Service' '/etc/systemd/system/multi-user.target.wants/boneServer.service'

Notice it copies your file to another place. Try rebooting and see if it works.




thumb‎ Embedded Linux Class by Mark A. Yoder