Starting a Program on the Jetson Nano Without a PC Connection

So far, I have compiled and executed programs on the Jetson through the terminal on my PC. I want have the Jetson run a given program on its own without having to be started by a PC. I’m envisioning something like what happens when you “offload” code onto an Arduino or STM32, allowing it to run on its own without a connection. Surely there has to be something similar for the Jetson. Could you please explain it simply? Thanks.

This depends on the nature of the program being run. It is best to explain what I mean with the “nature” of the program before spending time running it.

Some programs do not have any special requirements. Those programs don’t care if there is a GUI involved, and typically don’t interact with the GPU. These can just run at any time without regard to whether there is some special condition met (such as having a GPU set up).

Other programs may require the GUI to be running. Examples would be OpenGL programs or CUDA programs which depend on the Xorg server loading the NVIDIA GPU driver.

What resources does your program need to run?

The program is blink detection. It takes input from a CSI camera, does some image processing, and provides output via a GPIO pin.

This might or might not require a GUI, not sure. If you were to use ssh to log in to the Jetson, without any special options (e.g., don’t use “ssh -X” or “ssh -Y”), then can you start the program on command line? I ask because not setting DISPLAY (which associates with a GUI desktop) is the default of ssh, and it is necessary to know if this can run without the GUI.

Note: You can verify no display associated if “echo $DISPLAY” has no content. Content would appear something like “:0”. If DISPLAY is set, then you could first “unset DISPLAY”.

So far I’ve only connected with to the Jetson through serial (using Putty). How would I connect it with SSH?

Connecting via PuTTY would also work since there is no GUI forwarding over a serial console. Perform the same test listed above, but do so on serial console, and the result should answer if a GUI is required (try launching when there is no response from “echo $DISPLAY”…if it works, then no GUI is needed).

Note: PuTTY has both ssh and serial console available. You said you are using serial, but it is possible to also use PuTTY to use ethernet (ssh). You don’t need it for this test, but I highly recommend experimenting with ssh on PuTTY as well (it’s quite useful and has advantages when the system is not dead…serial console works pretty much until the hardware melts down).

I tried that command and it just returned to the next line without output. After that, I successfully ran a program through the terminal.

If a “DISPLAY” is needed, then usually it will fail with a message about being unable to find the DISPLAY. When it returns without doing anything, then it might be working, but only if this is what the program is intended to do (for example, if the program is intended to create a file, but not display anything, then perhaps the file succeeded in creation). At other times having the command return without doing anything would be a sign of silent failure (some programs appear to return, but are still running threads in the background…others truly exit with such a return behavior).

If you run this program, and it is functioning correctly, what behavior would you see? Are files written? Is there any kind of graphical display? Without knowing more it is hard to say.

Nothing is displayed. The Jetson will output a digital signal via one of its pins, which will be picked up by another (non-Jetson) board.

When you start this program via PuTTY, and no “DISPLAY” is set, does this digital signal output correctly? If so, then starting your program automatically at boot is likely a simple edit. If not, then more research is needed.

I need to get things together to test. I’ll get back to you soon.

I ran the test and the program outputs correctly. What’s next?

If you were to distribute commercially, then you’d want to make a systemd file to load as a service. The simpler way is to use the “/etc/rc.local” file and just run the content there. On older releases this file would always “just be there”, but on newer systems this file is optional. See first if you have file “/etc/rc.local”. My guess is that unless you are using an older release, then the file won’t be there.

This command will tell you the status of the use of that file, which is most likely not running:
systemctl status rc-local.service

Because this won’t be running (unless something has told it to) you would enable the service like this:
sudo systemctl enable rc-local.service

Then you would create the missing file in “/etc” with name “rc.local”. The permissions should be “-rwxr-xr-x 1 root root” (use “ls -l /etc/rc.local” once the file is created to see permissions). Here is the content you can copy and paste to create the skeleton of the file (use “sudo” with your favorite editor since only root should be able to write there):

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Place your custom content here...

exit 0

When the system boots it will now run content in this file as boot completes. What command name does your program use? I will pretend the command is “hello” (no such command, just illustration), and it is located at “/usr/local/bin/hello”. Normally full paths are used in this file for good reason, so use the full path. If this is a shell script, then some edits might be needed, so state what kind of program this is, e.g., compiled versus interpreted (such as Python)…this changes how you will want to launch the program. Also state if the program is to be run as root or some other user.

An example of finding out more about the program would be to run the command which examines it:
file /usr/local/bin/hello
(post what it says about the file type)

Also, state if your program, when run on command line, ever has output (e.g., error messages or other messages) to the command line. If it does, then be sure to mention the nature of that text (this can have an effect on logging and something with a lot of output could fill up the log files if not careful, but error messages might be good to log).

Once this is known it should be easy to add a single line to rc.local to launch your program.

I get this after running the enable command.

The unit files have no installation config (WantedBy, RequiredBy, Also, Alias
settings in the [Install] section, and DefaultInstance for template units).
This means they are not meant to be enabled using systemctl.
Possible reasons for having this kind of units are:
1) A unit may be statically enabled by being symlinked from another unit's
   .wants/ or .requires/ directory.
2) A unit's purpose may be to act as a helper for some other unit which has
   a requirement dependency on it.
3) A unit may be started when needed via activation (socket, path, timer,
   D-Bus, udev, scripted systemctl call, ...).
4) In case of template units, the unit is meant to be enabled with some
   instance name specified.

Is that to be expected?

The program is in Python and prints some basic stuff to the console (strings concatenated with ints).

Just to make sure I have this right, I would replace your commented code with the run command? (For me, that’s python3 followed by the file location). So far I’ve been running the program in a user I created, but it doesn’t really matter to me. And when you say the script runs upon bootup, does that mean as soon as the Jetson is powered up, or I do I still need to connect a port and login, etc?

Yes, that does happen on some systems. Here is a fix for that explained here:
https://www.linuxbabe.com/linux-server/how-to-enable-etcrc-local-with-systemd

What it comes down to is the default “/lib/systemd/system/rc-local.service” lacks a line for the “Install” section. The URL basically copies that file into the local configuration area at “/etc/systemd/system/”, but then adds the “Install” section. Then running “sudo systemctl enable rc-local.service” works.

The above assumes you’ve created the “/etc/rc.local” file (my previous post is what I recommend for your starting “/etc/rc.local” file (the URL only has the “exit” in it, but it really should have the shebang on the first line as well, and the comments are from what the Ubuntu package would provide if this were installed by default). You do need to make sure the permissions are correct on rc.local. One way to do this after you’ve created it:
sudo chmod 755 /etc/rc.local
(then verify “-rwxr-xr-x 1 root root”)

Before I tell you how to add your program to that file (rc.local) you should tell me if this program normally runs as root/sudo, or if it runs as another user. Placing content there runs as root unless sudo is used in the command (root is never asked for password to run as another user, so you can use sudo within the “root run” rc.local script and it will run as another user).

A second note is that a Python program may require some environment setup first which is normally present for a regular logged in user, but not necessarily present (yet) in rc.local at this moment during boot. So if you get an error related to environment, then this is easy to fix.

Given that, here is an example if your program is named “hello.py”, and if that program uses python release 3 and not 2 (you can use a command such as “which python2” or “which python3” to find a full path), and assuming you want the user to run as to be “mytestguy” (leave out all of the “sudo -u name” if not using a non-root user). Note you should always use full path to the python interpreter in this file:
sudo -u mytestguy /usr/bin/python3 /usr/local/bin/hello.py

My example uses a python program “hello.py” located in “/usr/local/bin”. Be sure your program is not just running from your home directory and is instead in a system directory so it is better protected.

My program runs under another user.

Then you would use the example above with “sudo” in it (just substitute the name of your user for the “mytestguy” example name). Just make sure your application is in a system location rather than a home directory. Technically, this could run in a home directory, but it is a bad idea for a number of reasons.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.