3

I'm trying to show my local IP on an LCD during startup. My script worked fine during normal testing via the command line, but when called at startup it doesn't seem to be able to fetch the IP.

I tried to call the script via crontab and init.d. Both sequence locations didn't return the IP. My obvious guess is that the interface isn't up yet. But when/where exactly can I call my python script so I can get the IP address and use it as a string?

import socket
import fcntl
import struct

def get_ip_address(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915,  # SIOCGIFADDR
        struct.pack('256s', ifname[:15])
    )[20:24])

print get_ip_address('eth0')
# prints the local IP when running via command line
# gives error when running during startup/boot:
# -->(struct.pack('256s', ifname[:15]) / IOError: [Errno 99] Cannot assign requested address)
  • That is an absurdly long statement. It would be significantly easier to debug If you broke it up properly. – Jacobm001 Nov 19 '15 at 18:58
  • It shows the 3 ways in python that I tried to get the IP, with the errors under it. I agree but if I don't include the methods and/or errors, others will tell my question is incomplete. – EDP Nov 19 '15 at 19:13
  • And they would be correct. I was commenting on the fact that the code was written poorly and should be refactored. – Jacobm001 Nov 19 '15 at 19:16
  • That's most probably because I started python just a couple hours ago. I get the IP with all 3 methods when I run it via command line. Only during boot sequence it gives those errors. – EDP Nov 19 '15 at 19:20
  • Code is updated with much more simplified version – EDP Nov 20 '15 at 7:39
1

It depends what you question is. If you just want the IP the following script will display it. The script in /etc/rc.local used to contain similar code, but did not run by default because of execution bits.

#!/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.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi

# If running headless (i.e. default RCA video)
if /opt/vc/bin/tvservice -s | grep 'NTSC\|PAL'; then
  echo $(hostname) is running Headless
  /opt/vc/bin/tvservice -s
else
  echo $(hostname) is running hdmi
fi

exit 0

If you question is how to run a Python script on startup you should be able to find answers on this site. The actual content of the script is (almost) irrelevant.

EDIT Your question is still vague. hostname -I will return the IP address as a string, and can be called anytime after IP has been allocated. There are many more complex ways of getting IP (using Python or almost any other language).

Including in /etc/rc.local will run at login (when it should be valid) but there are many other possibilities. NOTE Jessie runs systemd, although this still seems to support older scripts.

  • My question is not about how to run a Python script. It does run during startup. It does get my IP correctly when ran via command line. It just doesn't get my IP when run during boot. I tried your way, but $ echo $_IP after booting still gives me an empty string – EDP Nov 20 '15 at 7:43
  • @EDP It should display the IP during boot (which appeared to be your question). Obviously $_IP is not inherited by later processes. You could do so, but why. What EXACTLY are you trying to achieve? – Milliways Nov 20 '15 at 7:47
  • I've edited my question I hope it's more clear now – EDP Nov 20 '15 at 8:51
1

If you suspect your issue comes from the fact that your script is being run before the network is configured, consider running it via systemd with network-online.target as a dependency:

Create a file /etc/systemd/system/my_service.service:

[Unit]
Description=my service
After=network-online.target

[Service]
ExecStart=/path/to/script.py

[Install]
WantedBy=multi-user.target

and run:

sudo systemctl enable my_service

Your script should start on the next reboot

0

You need to add some delay before reading the ip_address. Looks like the script is being executed before the ip-configuration.

Adding the following code to your code will fetch you the ip:

import time
time.sleep(10)

import socket
import fcntl
import struct

def get_ip_address(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915, #SIOCGIFADDR
        struct.pack('256s',ifname[:15])
    )[20:24])

ip_addr = get_ip_address('wlan0')
sense.show_message("My IP:")
print ip_addr
  • Note that the OP may have to tweak the delay value depending on how long the network configuration takes on their RPi. With only 10 seconds of delay, this is likely to work in a hit-and-miss manner. – Dmitry Grigoryev Apr 3 '17 at 8:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.