Project

General

Profile

Launching Linux Application on Startup

Added by Okan Çalış over 2 years ago

Hi,
I want to adjust the ARM so that it starts an application automatically after startup (or login). There seems to be more than one way to do that, two of which are covered in your wiki. I tried applying them with a dummy script in /home/root/ that just echoes "Hello World!"

Linux Startup Process - Systemd
I tried this method; however, it didn't do anything beside printing "Starting <service.name>" at startup.

ARM Software FAQs
This method put a symlink /etc/rc2.d/S20<name> for my script in /etc/init.d. But it didn't run at the startup, either.

There is also another way where you append the commands to be executed to /etc/profile. For me, it works most of the time. However, in my main application, which uses GadgetFS to connect to a USB host, it throws an error saying "device or resource is busy" just as it tries to open the device. In other words, at line "int fd = open("musb-hdrc", O_RDRW)", fd becomes negative (which doesn't happen if I run the executable myself).

Do you have any ideas?
Thanks in advance,
Okan


Replies (8)

RE: Launching Linux Application on Startup - Added by Jonathan Cormier over 2 years ago

Okan Çalış wrote:

Hi,
I want to adjust the ARM so that it starts an application automatically after startup (or login). There seems to be more than one way to do that, two of which are covered in your wiki. I tried applying them with a dummy script in /home/root/ that just echoes "Hello World!"

Linux Startup Process - Systemd
I tried this method; however, it didn't do anything beside printing "Starting <service.name>" at startup.

This is the correct method. Please attach your service file and any logs. Also explain what you expect to happen and what is actually happening.
Note that applications started via this method won't print to the screen, instead there output will get sent to the journal. Running systemctl status service.name should show you the current status of your program and any output it printed.

ARM Software FAQs
This method put a symlink /etc/rc2.d/S20<name> for my script in /etc/init.d. But it didn't run at the startup, either.

This is based on the older init.d startup process. Which is deprecated in this filesystem. It might still work but not recommended.

There is also another way where you append the commands to be executed to /etc/profile.

As far as I know, this will only execute when you login to any user account. I do not recommend this for starting an application on device startup.
Quote from the internet:

The /etc/profile file is not very different however it is used to set system wide environmental variables on users shells. The variables are sometimes the same ones that are in the .bash_profile , however this file is used to set an initial PATH or PS1 for all shell users of the system.

For me, it works most of the time. However, in my main application, which uses GadgetFS to connect to a USB host, it throws an error saying "device or resource is busy" just as it tries to open the device. In other words, at line "int fd = open("musb-hdrc", O_RDRW)", fd becomes negative (which doesn't happen if I run the executable myself).

Do you have any ideas?
Thanks in advance,
Okan

RE: Launching Linux Application on Startup - Added by Okan Çalış over 2 years ago

Linux Startup Process - Systemd
I tried this method; however, it didn't do anything beside printing "Starting <service.name>" at startup.

This is the correct method. Please attach your service file and any logs. Also explain what you expect to happen and what is actually happening.
Note that applications started via this method won't print to the screen, instead there output will get sent to the journal. Running systemctl status service.name should show you the current status of your program and any output it printed.

You're right. This one was already working, but I didn't realize it because it couldn't print anything. Adding "StandardOutput=tty" to the service file solved this. Here's my service file:

[Unit]
Description=ehagtm Receiver
After=init_ehagtm.service getty@tty1.service serial-getty@tty1.service serial-getty@tty2.service systemdlogind.service

[Service]
ExecStart=/sbin/ehagtm_arm
StandardOutput=tty
StandardError=tty
Type=oneshot

[Install]
WantedBy=multi-user.target

However, the app still doesn't act as expected at the startup. GadgetFS starts, but it can't get any events, so the program keeps polling forever.

If I manually start it (either by typing app_name or by starting the service systemctl start app.service), it works properly. But it does not at the startup.

P.S. The program doesn't require any std input.

RE: Launching Linux Application on Startup - Added by Okan Çalış over 2 years ago

I also tried switching Type to idle to ensure the service is not invoked before all other jobs are completed, but that didn't work, either.

Isn't there a way that simulates me typing ./app_name with the keyboard after tty is available? I really don't need it to run parallel to any services; it's the main application, after all.

Thanks again.

RE: Launching Linux Application on Startup - Added by Jonathan Cormier over 2 years ago

Okan Çalış wrote:

Linux Startup Process - Systemd
I tried this method; however, it didn't do anything beside printing "Starting <service.name>" at startup.

This is the correct method. Please attach your service file and any logs. Also explain what you expect to happen and what is actually happening.
Note that applications started via this method won't print to the screen, instead there output will get sent to the journal. Running systemctl status service.name should show you the current status of your program and any output it printed.

You're right. This one was already working, but I didn't realize it because it couldn't print anything. Adding "StandardOutput=tty" to the service file solved this. Here's my service file:

[...]

Good catch. I'd guess that your service type should be simple instead of oneshot since your program isn't expected to exit. But idle is similar to simple and that didn't help...

However, the app still doesn't act as expected at the startup. GadgetFS starts, but it can't get any events, so the program keeps polling forever.

If I manually start it (either by typing app_name or by starting the service systemctl start app.service), it works properly. But it does not at the startup.

P.S. The program doesn't require any std input.

Hmm I'm not sure what could be different between when you run it manually vs automatically.

I'd suggest using strace to see if you can determine where things break. strace will output every system call your app makes so if you run it in both working and broken cases maybe you can detect whats going wrong.

strace -o /home/root/trace.log /sbin/ehagtm_arm

and
ExecStart=strace -o /home/root/trace2.log /sbin/ehagtm_arm

RE: Launching Linux Application on Startup - Added by Jonathan Cormier over 2 years ago

Note that you can filter the strace output to reduce the amount of data you get. https://stackoverflow.com/a/30034030

RE: Launching Linux Application on Startup - Added by Okan Çalış over 2 years ago

Hi, Jonathan,
I did what you suggested.

The application seems to fail at startup because of a poll call.

Startup trace:

poll([{fd=4, events=POLLIN|POLLOUT|POLLHUP}], 1, -1) = ? ERESTART_RESTARTBLOCK (To be restarted)

Manual launch trace:

poll([{fd=4, events=POLLIN|POLLOUT|POLLHUP}], 1, -1) = 1 ([{fd=4, revents=POLLIN}])

This is the major difference between two traces (apart from dynamic address differences etc). After this line, the startup application waits indefinitely until a SIGTERM. But I still don't know what makes it fail to poll properly.

RE: Launching Linux Application on Startup - Added by Jonathan Cormier over 2 years ago

poll([{fd=4,

You need to look higher up in the strace log to find out which file is opened as fd (file descriptor) 4. Note that the file descriptors are reused so a file can be opened early on get fd 4 and then be closed and a new file could get fd 4 so start at the poll and search upwards.

Your looking for a line similar to the following, the open() function returns the fd, 3 in this case.

open("/tmp/test", O_RDONLY)             = 3

RE: Launching Linux Application on Startup - Added by Jonathan Cormier over 2 years ago

You also want to figure out where this poll is happening in your code or perhaps a driver you've included. And what action the code is supposed to take when receiving the ERESTART_RESTARTBLOCK signal.

    (1-8/8)
    Add picture from clipboard (Maximum size: 500 MB)