Tiny Core Linux

Tiny Core Base => Raspberry Pi => Topic started by: xuraax on August 13, 2022, 02:40:01 AM

Title: Running Python Scripts at Startup
Post by: xuraax on August 13, 2022, 02:40:01 AM
I would like to run a Python script, which runs well from command line, directly after booting on a headless Pi.

I have read previous help on this topic but nothing seems to work for me including running the script with &, inserting a sleep 60 delay before the " python3 /home/tc/trial.py & " in the bootlocal.sh file. Even a simple python file consisting of an infinite loop which prints just a string to screen. Inserting " echo 'Hello There' " directly into bootlocal.sh also produces nothing. Clearly I am missing something quite basic.

Any help appreciated.
xuraax
Title: Re: Running Python Scripts at Startup
Post by: Rich on August 13, 2022, 07:35:57 AM
Hi xuraax
Try adding the command to the end of  .profile  in your home directory.
Title: Re: Running Python Scripts at Startup
Post by: xuraax on August 16, 2022, 03:53:27 AM
Hi Rich.
Thanks for your suggestion.
I can confirm that the script does run when invoked from the .profile file. However for some reason it does not operate in the same way as it does when run from the command line. I still need to analyse this properly.

I first thing I noticed was the following:

My script turns on an LED to signify that it is functioning and then goes into a loop to establish communication via the UART. Each attempt is confirmed by a print statement which signals the attempt number.

The strange thing is that even if a wait for several minutes before I SSH into the system when I am certain that the link has been established, the message that appears on the screen is as if the attempt in communication has just started.

My other question is: why did this script not work at all in bootlocal.sh?

Regards
Title: Re: Running Python Scripts at Startup
Post by: bmarkus on August 16, 2022, 04:35:15 AM
It would be good to see your Python script and how is it called. Without information it is just guessing.
Title: Re: Running Python Scripts at Startup
Post by: xuraax on August 16, 2022, 10:41:47 AM
It would be good to see your Python script and how is it called. Without information it is just guessing.

I have no problem with sending the script but I must warn you it is about 200 lines long and, coupled with the fact that I am not an expert programmer, it can get confusing. Just tell me how to proceed and i will comply.

The script is built around an old RPI to which I added a small 2 transistor circuit to the UART to interface over the K-line to my bike's ECU. Once logged on it collects all data and sends it to a csv file which I further process off line using Excel. The idea is to collect live data whilst on the move.

Regards
Title: Re: Running Python Scripts at Startup
Post by: xuraax on August 16, 2022, 03:06:10 PM
After writing the above mail I realised I could demonstrate what is happening by writing a very simple script which I called trial.py and invoke that in the .profile file. The script simply consists of the following:

Code: [Select]
import time
i=0
while True:
    print("Sample no.: ",i)
    i+=1
    time.sleep (1)
   

In the .profile file I inserted

Code: [Select]
sudo python3 trial.py
Note that I need to use sudo in my own program since this is required to access the UART.

After saving and rebooting and SSHing into RPI one notes that the first thing that comes on the screen is "Sample no.: 0"

Keeping the script running and exiting SSH and then reentering again with SSH, the screen still comes up with "Sample no: 0" even if I allow some time to pass before reconnecting.
Also with the script is running and you do ^C the script appears to terminate with the correct error message. However in fact the script is still running in the background and doing
Quote
ps aux
shows that python3 trial.py is still running with its own job number.
Title: Re: Running Python Scripts at Startup
Post by: patrikg on August 16, 2022, 03:19:07 PM
If i don't misunderstand your request, you could do it like this.

.profile is running when entering the shell.

Too keep the script running after exiting the shell you could add nohup to the script so the shell don't exit its child processes.   

https://linuxhint.com/how_to_use_nohup_linux/
Title: Re: Running Python Scripts at Startup
Post by: xuraax on August 17, 2022, 09:56:35 AM

Too keep the script running after exiting the shell you could add nohup to the script so the shell don't exit its child processes.   


nohup is an interesting command but it does not achieve what I want. What I am looking for is the following:

1. when I power up my RPI, my script initiates and goes about its work collecting data loop after loop.
2. at some later point when I want to "look in" I would like to SSH into the RPI to see what is happening during that particular loop. if say at teh point of entry the variable in my trial.py happens to be i = 1000, I would like to see teh following on screen:
Quote
Sample no.: 1000
3. while here I could decide to interrupt my loop and stop the script completely or continue monitoring on screen the data being collected.

In the past, I have done something similar (but not with autostart) by using TMUX which allows you to look into a process by attaching or deattaching from that process.

Title: Re: Running Python Scripts at Startup
Post by: bmarkus on August 17, 2022, 10:01:40 AM
Use 'screen'
Title: Re: Running Python Scripts at Startup
Post by: xuraax on August 17, 2022, 01:50:15 PM
Screen appears to be another version of tmux.

what I tried was to insert in the .profile file:
Code: [Select]
screen -S mysession
sudo python3 trial.py


in the hope that, when I later ssh into the box, I can do:
Quote
screen -r mysession
to reconnect but this did not work because I had not deattached from "mysession" using
Quote
^A^D
after initiating the script.

Doing:
Quote
screen -ls
listed 2 still attached processes named "mysession" (why 2?)

I guess this method could work if I am able to somehow invoke ^A^D from the .profile file to deattach "mysession".

any ideas?
Title: Re: Running Python Scripts at Startup
Post by: FlyingDutchman on August 17, 2022, 04:21:34 PM
Hi xuraax,

Just my 2 cents here, as I know almost nothing about Python.
I think you can execute Python code from bootlocal.sh (I don't see any reason why not), but I don't think you can write any output to a terminal or console. When bootlocal.sh runs, there is no tty connected to that process, afaik.

The easiest way I can see is to log your output to a file and then reading that file when you ssh into the system. If you want that fully automated, you could add
Code: [Select]
tail -f <FILE> to your .profile script.
To avoid the file growing until eternity, maybe you should also write some kind of cleanup mechanism that clears the whole file, or certain entries in the file.

Cheers.
Title: Re: Running Python Scripts at Startup
Post by: Rich on August 17, 2022, 05:37:28 PM
Hi xuraax
... The script is built around an old RPI to which I added a small 2 transistor circuit to the UART to interface over the K-line to my bike's ECU. Once logged on it collects all data and sends it to a csv file which I further process off line using Excel. The idea is to collect live data whilst on the move.
So it sounds like you probably have the data collection working and now want to be able to display snapshots periodically.

My recommendation is you run your program in the background and do not print anything to the screen.
Print the data to a file (Data.txt) and overwrite the file whenever fresh data comes in.

Use a second file (Status.txt) initialized to 0 to synchronize accessing the file:
When you want to read the contents of Data.txt, set the contents of Status.txt to 1.
When your python program sees the read request and is done updating Data.txt, it sets the contents of Status.txt to 2.
As long as the contents of Status.txt remains equal to 2, your python program skips updating Data.txt.
When you see Status.txt has been set to 2, it is safe to read the file.
After you have read Data.txt, you set Status.txt back to 0 which tells your python program it is safe to resume updating Data.txt.
Title: Re: Running Python Scripts at Startup
Post by: Rich on August 17, 2022, 10:59:29 PM
Hi xuraax
The following can be used to monitor the contents of Status.txt and display the contents of
Data.txt when your python program signals that it is safe to do so.
Code: [Select]
#!/bin/sh

DataFile="Data.txt"
StatusFile="Status.txt"

# Create Status file if it doesn't exist.
[ -f "$StatusFile" ] || echo 0 > "$StatusFile"

while true
do
sleep 2
status="`cat $StatusFile`"

case "$status" in
0) # Signal that we want to read DataFile.
echo 1 > "$StatusFile"
;;

1) # Wait for status to change to 2.
continue
;;

2) # Clear the screen, display the data, and reset StatusFile to 0.
clear
cat "$DataFile"
echo 0 > "$StatusFile"
;;
esac
done
Title: Re: Running Python Scripts at Startup
Post by: xuraax on August 18, 2022, 01:38:14 AM

I think you can execute Python code from bootlocal.sh (I don't see any reason why not), but I don't think you can write any output to a terminal or console. When bootlocal.sh runs, there is no tty connected to that process, afaik.


Thank you for your suggestions. In fact my full script includes also an LED output to signal what is happening and one input to test the position of a push button. As you proposed I have removed all tty output and rely on the LED to tell me if the script has started, if connection has been established and then that data is being collected and stored to a file. The push button interrupts the loop and closes the data collection file and then the script itself.

This still did not work for me in bootlocal.sh but does work using the .profile file. Maybe the reason why the former method is not working for me could be because my script needs to use UART 0 which is probably being used by the system as console output during the booting process.

Anyway...I still would like to explore further the use of
Quote
screen
invoked from the .profile file and it seems that if I can manage to invoke
Quote
^A ^D
from here I may be able to achieve my aim. Indeed looking further into the commands available in
Quote
screen
I noted a command called
Quote
detach
which I had hoped would do the trick for me but alas no joy!
Title: Re: Running Python Scripts at Startup
Post by: xuraax on August 18, 2022, 03:11:21 AM

The following can be used to monitor the contents of Status.txt and display the contents of
Data.txt when your python program signals that it is safe to do so.


Thank you Rich for your suggestions. I will consider it. Another possibility would be to save to a different .csv file every, say, 1000 samples from the script running in background and just open up a particular .csv when I log in with ssh.

I still would like to see if can "peek in" into my running script using "screen" if it is at all possible.
Title: Re: Running Python Scripts at Startup
Post by: patrikg on August 18, 2022, 03:54:22 AM
You can remove the tty from command line argument to the kernel, the console.
So you free the UART.
And remove the tty in inittab.


Title: Re: Running Python Scripts at Startup
Post by: patrikg on August 18, 2022, 04:38:41 AM
You can remove the tty(serial) from command line argument to the kernel, the console.
(/boot/cmdline.txt). So you free the UART/serial port.

And remove the getty tty(serial) in /etc/inittab.
And remove the startserial.sh if you running that script, in boot script.

When i referring to tty(serial) you have to consider that the serial port have lots of different names.
console=serial0,115200
console=ttyAMA0,115200

Just have the console=tty1 in kernel command line argument(tty1 is the first text mode virtual console.), if you using raspberry pi with hdmi.

You can remove all console and using headless raspberry pi with out any console.
Just access the RPI with network ssh.
You can also do the following when using headless rpi:
Add the line to config.txt to gain little more memory, because you don't use the hdmi/gpu
 
Code: (bash) [Select]
gpu_mem=16

And the user tc have to have rights to the port, lots of linux distributions uses some type of group to the serial port, so if you add the default tc user the the correct group you don't need to use sudo for your user to use the serial port.

To easy see what group you should add the tc user to, you just list the serial device in dev.
Lets see what my arch linux pc com1 serial port.

[
Code: (bash) [Select]
root@arch-new ~]# ls -la /dev/ttyS0
crw-rw---- 1 root uucp 4, 64 18 aug 09.18 /dev/ttyS0
[root@arch-new ~]#

Ahhh it's uucp.
So if my regular user need com1 I just need to add that user to group uucp.


Happy hacking.
Title: Re: Running Python Scripts at Startup
Post by: xuraax on August 19, 2022, 01:37:18 AM

And the user tc have to have rights to the port, lots of linux distributions uses some type of group to the serial port, so if you add the default tc user the the correct group you don't need to use sudo for your user to use the serial port.

To easy see what group you should add the tc user to, you just list the serial device in dev.
Lets see what my arch linux pc com1 serial port.

[
Code: (bash) [Select]
root@arch-new ~]# ls -la /dev/ttyS0
crw-rw---- 1 root uucp 4, 64 18 aug 09.18 /dev/ttyS0
[root@arch-new ~]#

Ahhh it's uucp.
So if my regular user need com1 I just need to add that user to group uucp.


Happy hacking.

Thank you, i will certainly try out several of your suggestions.

With regards to the one above, I have tried in the past, admittedly on other versions of linux, to add my user to the correct group but this still was not enough. I needed also to give read/write options to the users besides root. This worked until the next boot, which reinstated the restrictions. The second line from your code quote would always reset to: crw--w---- etc. after reboot.
Title: Re: Running Python Scripts at Startup
Post by: FlyingDutchman on August 19, 2022, 02:39:57 AM
Hi xuraax,

To find out why your script won't run from bootlocal.sh, you could add debug code into your python script: at important points within your script, log variable values to a log file and make sure to redirect error messages to a log file. Then after boot, you can verify why the script does not behave as expected.

Does the system log (/var/log/messages) tell you anything useful?

Alternatively, you could connect a screen to your Pi while starting up. Per default, TinyCore starts a shell for the tc user during boot and shows boot output on the terminal for that user. Although often it is a lot of output within a couple of seconds. In the past, I even had to resort to recording the output on my smartphone and then playback in slow motion to capture the error messages that I needed :-)
Title: Re: Running Python Scripts at Startup
Post by: polikuo on August 19, 2022, 10:39:09 AM
I guess your script requires user privilege
bootlocal.sh is run by root
Code: [Select]
su tc -c 'python3 yourscript'
Title: Re: Running Python Scripts at Startup
Post by: xuraax on August 19, 2022, 12:09:58 PM
I guess your script requires user privilege
bootlocal.sh is run by root
Code: [Select]
su tc -c 'python3 yourscript'

Why is this better than?:
Code: [Select]
sudo python3 myscript
Title: Re: Running Python Scripts at Startup
Post by: polikuo on August 19, 2022, 12:14:03 PM
Every command in bootlocal.sh is run by root
Every command in .profile is run by tc
To run a command as tc in bootlocal.sh, you need to switch user.

Code: [Select]
sudo python3 myscript
This line will be run as root, or may not execute at all.
Title: Re: Running Python Scripts at Startup
Post by: xuraax on August 29, 2022, 02:11:24 PM
Hi,

I have just discovered why my Python script does not run at all when run from bootlocal.sh. It appears that in this mode, the script starts. It then stops when it attempts to import the "serial" module issuing an error which is not reported when you connect headless but can be seen when connecting a monitor to the HDMI port.

What can I do to get the "serial" module visible ALSO at startup (from root)?
Title: Re: Running Python Scripts at Startup
Post by: Rich on August 29, 2022, 10:53:03 PM
Hi xuraax
... It then stops when it attempts to import the "serial" module issuing an error ...

What is the error message?
Where does the imported module come from?
Does it get download over the network? If so, it's possible the network is not up yet.

This will block (up to 60 seconds) until the network is up:
Code: [Select]
# Wait for network to come up
SEC="60"
while [ $SEC -gt 0 ]
do
        SEC=$(($SEC - 1))
        ifconfig | grep -q "Bcast:" && break
        sleep 1
done
Title: Re: Running Python Scripts at Startup
Post by: xuraax on August 30, 2022, 02:12:11 AM
The problem is not network related.

When I boot up with the USB dongle removed I get the same message. When I then run "sudo python3 test.py" there is no issue which implies the python module "serial" is inside somewhere.
The message I get at startup is:

ModuleNotFoundError: No Module named 'serial'.

Python reports the script name and the line line number where my offending "import serial" resides.
Also when I remove the offending line from my script, the script runs properly at boot up.

it seems running python3 from root is different than running python3 from sudo.
Title: Re: Running Python Scripts at Startup
Post by: patrikg on August 30, 2022, 08:29:31 AM
My suggestions is to try following.

Add the path to the working directory to sudo like this in bootlocal.sh:
Code: (bash) [Select]
sudo -D /home/tc /home/tc/test.py
So sudo change the working directory before executing the test.py script.

Add the shebang line at the first line in the test.py python file like this:
Code: (bash) [Select]
#!/usr/bin/env python3

Add the execution bit to the python file:
Code: (bash) [Select]
sudo chmod u+x /home/tc/test.py


Happy hacking :)
Title: Re: Running Python Scripts at Startup
Post by: Paul_123 on August 30, 2022, 08:33:22 AM
I'm pretty sure there is no serial module included with python3.  You must have installed pyserial into a local user account which is not available when using bootlocal.   Look in /home/tc/.local/lib/......  do you see python modules?

What extensions are loaded
Title: Re: Running Python Scripts at Startup
Post by: xuraax on August 30, 2022, 10:22:36 AM
 Will try but in the meantime, can you please answer the below questions?

Your suggestion 1: understood.
Your suggestion 2: What does this do? I always understood that a line started with # is ignore by the interpreter.
Your suggestion 3: Why does the execution bit need to be set given that this programs runs in the python3 interpreter?

Thanks

My suggestions is to try following.

Add the path to the working directory to sudo like this in bootlocal.sh:
Code: (bash) [Select]
sudo -D /home/tc /home/tc/test.py
So sudo change the working directory before executing the test.py script.

Add the shebang line at the first line in the test.py python file like this:
Code: (bash) [Select]
#!/usr/bin/env python3

Add the execution bit to the python file:
Code: (bash) [Select]
sudo chmod u+x /home/tc/test.py


Happy hacking :)
Title: Re: Running Python Scripts at Startup
Post by: xuraax on August 30, 2022, 10:44:47 AM
I'm pretty sure there is no serial module included with python3.  You must have installed pyserial into a local user account which is not available when using bootlocal.   Look in /home/tc/.local/lib/......  do you see python modules?

What extensions are loaded

It has been some time since I installed pyserial so I don't recall how I did it. Probably through pip.

Here are the contents of the directories you mentioned:

~/.local/lib/python3.8/site-packages/
pyserial-3.5.dist-info/
serial/

Both are directories.

The first looks like it contains text files.
The second contains several python scripts but none of these are called "serial.py"

For me the simplest solution would be to have all modules available even from root. i hope this is possible?

regards
Title: Re: Running Python Scripts at Startup
Post by: Paul_123 on August 30, 2022, 10:52:18 AM
So you installed pyserial using pip with the --user flag.   That will only work for user sessions.    Delete all of the python libraries from .local

Then install the extension py3.8serial.tcz
Title: Re: Running Python Scripts at Startup
Post by: patrikg on August 30, 2022, 11:10:06 AM
When the execution bit is set, you telling the system that the file is executable.
It can be some elf(bin asm) file or it can be a script file. If it's a script file the system don't know what interpreter it should run.

So you need to tell the system what interpreter it should run.
You telling that in the first line, and that is also know as the shebang line.

You can see that line in lots of script languages, like in bash script.
Lets make an example.
First make this file.

nano test

Code: (bash) [Select]
#!/usr/bin/bash
echo "Hello World!"

Then you have to tell the system that the file is executable, you do that with the chmod command.

Like this:
Code: (bash) [Select]
chmod u+x test
Then you can test if it works with just the line
Code: (bash) [Select]
./test
The system loads the script and execute the first line program, and feeds the rest of the script to the interpreter in this case it's bash.
Why you have to add "./", that is just for telling the command interpreter that you trying to execute some file from your current directory.

You don't use the extension of the file to tell the system what interpreter to use. (like in Windows)
You just add the shebang line. And add the executing bit to the file.

You don't need to tell what interpreter to use when calling the script in the command line. You have provided that in the script.
And the filename can be what ever you like.
Unix don't use the filename extension of the file to determine what to do.
Title: Re: Running Python Scripts at Startup
Post by: xuraax on September 01, 2022, 03:11:45 AM
@Patrickg

Thank you for the extensive explanation.

@Paul_123

In the end your suggestion to install py3.8serial.py worked for me.

My only, small, regret is that I have been unable when attaching headless, to "peek" into the still running script to monitor the progress. I have experimented with suggestions to use screen in the following 2 ways:

Code: [Select]
screen -S dummy -d -m python3test.py exec $SHELL
OR

Code: [Select]
screen -dmS dummy
screen -S dummy -p 0 -X stuff "python3 test.py\n"

These had some limited effect when included in the .profile method but none at all when using the bootlocal.sh method

 
Title: Re: Running Python Scripts at Startup
Post by: Paul_123 on September 01, 2022, 08:47:52 AM
Your best bet is to write to a log file.   Then just use tail to monitor.

tail -f logfile

If you don't need to keep the data, just write to the /tmp directory, but make sure you track the file size to make sure you don't fill up memory.   You can use python's logging functions to rotate the logs to keep the size under control.
Title: Re: Running Python Scripts at Startup
Post by: xuraax on September 03, 2022, 04:21:50 AM
Your best bet is to write to a log file.   Then just use tail to monitor.

tail -f logfile

If you don't need to keep the data, just write to the /tmp directory, but make sure you track the file size to make sure you don't fill up memory.   You can use python's logging functions to rotate the logs to keep the size under control.

Does that log file need to have a special format?
The reason I ask is because my script already sends collected data in text format to a .txt file.

my test script opens up a text file and writes some text followed by CR every second until the loop ends after 100.

When I tried
Quote
tail -f test.txt
nothing happened until my script reached the end, at which point "tail" returned all the 100 lines in the file and waited there.
Title: Re: Running Python Scripts at Startup
Post by: Paul_123 on September 03, 2022, 08:09:18 AM
Logging is just a text file.  It’s likely because you are not flushing buffers writing to disk.  It’s easier to just use the built in logging
Title: Re: Running Python Scripts at Startup
Post by: patrikg on September 03, 2022, 09:15:37 AM
You can run linux sync command to flush.
Title: Re: Running Python Scripts at Startup
Post by: Rich on September 03, 2022, 12:03:03 PM
Hi xuraax
... my test script opens up a text file and writes some text followed by CR every second until the loop ends after 100. ...
After each write, do something like the following:
Code: [Select]
open status.tmp
write the same text to status.tmp
close status.tmp
os.system('sync')
os.system('mv -f status.tmp status.txt')
Now anytime you want to see the current status, just:
Code: [Select]
cat status.txtYou won't have to deal with a file that keeps growing. No risk of reading a partially updated file.
Title: Re: Running Python Scripts at Startup
Post by: xuraax on September 04, 2022, 02:23:28 AM

After each write, do something like the following:
......
......
You won't have to deal with a file that keeps growing. No risk of reading a partially updated file.

Thank you very much for this very interesting proposal. At this stage I think I will just forgo this requirement and concentrate on the main job of the script.

I take this opportunity to thank all who have contributed with suggestions.