7

Many questions have been asked about how to find my Pi on my network. Others - including myself - have time consuming issues while trying to deploy a batch of fresh Pi's.

While the creation of custom images could be a solution for these issues, I'm wondering if there are other solutions.

With (only) the /boot directory open for access on regular machines (Win/OSX), would it be possible to use /boot/cmdline.txt to pipe text to a bash script, run it and delete it afterwards?

2

You CAN cause code to be executed by messing with the kernel command line. The most obvious method is to replace init with something else. The most common application of this is to launch a shell very early in the boot process, usually because you need to fix something or because everything else is very badly broken, eg:

init=/bin/bash

Keep in mind that at this point in the boot process, the filesystems are all still mounted read-only. In addition, there is a whole bunch of things that just won't work correctly. Because you don't have a real init running, shutdown and reboot won't work. You have to manually remount the root filesystem read-only and call reboot -f to reboot, for example.

I have no idea if you can pass arguments to bash in this manner. I have never tried. In theory, if you can pass -c to bash, you can tell that bash process to do anything. But it might turn into a fairly long argument, and I don't know if the kernel would allow such things.

Second thing you can do. You can copy an initial ramfs (initramfs) to the filesystem, and configure the bootloader to use it in config.txt. There are several ways to get scripts into an initramfs to do special things. You'll have to prepare a special initramfs for this purpose though (see initramfs-tools(8)), so I am not sure if this is a better solution than a custom image.

You could include the script in /boot (I laughed at your suggestion about "regular" machines, but this would be the bit you can access from those machines) and attempt to launch that using the kernel init line, but files on dos filesystems aren't executable unless you make it so for the entire filesystem.

If it was me, I'd make a custom image that uses dhcp to configure the network, and that contains a custom script that runs at boot. This script checks for a specific file which acts as a flag. If the file exists, do nothing. If not, configure things, then create the flag file.

Your config script could even pull the real thing from an http server. This means you don't have to make a new image if you have to tweak something.

That should be the least stressful solution.

One final possibility, but you'll have to do this on a "non-regular" machine :-) You can mount the ext4 filesystem to a loop device and copy files to it without writing it to sdcard first. For a standard Raspbian Jessie image, it would be something like this:

sudo losetup /dev/loop0 /tmp/gw.img -o 62914560
sudo mount /dev/loop0 /mnt
sudo cp /my/superduper/script.sh /mnt
sudo umount /dev/loop0
sudo fsck -f /dev/loop0 # This is optional
sudo losetup -d /dev/loop0

I like to do a forced fsck on my filesystems before making images. Sets the mount count to zero on first boot :-)

EDIT: After many months and more experience. You want to look at u-boot. Replace the boot-loader with u-boot. This can be done from a "regular machine". Once you have u-boot in place, you can either network-boot a distribution from which you can easily flash the sd-card, or you could in theory flash the card directly, though I have no idea how hard that would be.

Essentially u-boot brings network-boot to the Raspberry Pi, something it does not support on its own.

  • Ok, file system is readonly at that stage. What about init=script & init? The script would run in background while init starts up normally. The script would need some condition checking at the beginning and e.g. continue when init has finished its work. – Thomas Weller Aug 31 '16 at 20:28
  • 1
    Using & to background something is a shell thing. Unless you tell the kernel to run a specific command in a shell (eg: bash -c "some command & another command") that won't work, and I already think this is a bad idea. But I did extend my answer and added the u-boot option, something I discovered recently. – izak Aug 31 '16 at 22:06
  • 1
    Just finished trying ;-) No, it really does not work – Thomas Weller Aug 31 '16 at 22:08
1

I wouldn't recommend touching anything in the boot area (other than config.txt) unless you have a detailed understanding of what that stuff is doing. cmdline.txt isn't designed to run things when the RPi starts. It's used to pass parameters to the Linux kernel on boot.

I would suggest doing this all through SSH. A script on your desktop could push a bash/python/java/c/whatever program to the RPi, execute it, and then delete it when it's finished. Add threading to the script on your desktop and you can send it out to as many devices as you want all at the same time.

  • 1
    That's how we do it now but I'm looking for a more easy solution. – EDP Jan 30 '16 at 14:57
  • 1
    Read: run the setup client-initiated rather than server-initiated – EDP Jan 30 '16 at 15:15
  • @EDP: there's no way to get what you want simply by editing the boot position. You could write a script that pulls the file from a server on the RPi's first boot, and then have that program remove the startup script. That would require you to use a custom image. – Jacobm001 Jan 31 '16 at 1:13
  • 1
    "A script on your desktop" - Which script on my desktop? At the first boot, there's no script on the Desktop. "Doing this all through SSH" - at the first boot the Pi might not have the correct Ethernet or WLAN settings. – Thomas Weller Aug 31 '16 at 20:25
  • You don't even need threading check out the fabric project. IIRC its only rewuirement is SSH – Steve Robillard Sep 1 '16 at 17:15
-2

You may want to look at my project Nard which has a solution for your problem:

1) Each SD-card can be assigned an unique ID with a regular Windows PC as described here:
http://www.arbetsmyra.dyndns.org/nard/#devsettingsid

2) Power on all your Pis

3) Disable the PC firewall if possible

4) Open a DOS prompt window and ping the subnet broadcast address

5) List the ARP table with Windows command "arp -a". In the list you will find the MAC and IP addresses of all nearby Raspberry Pi.

6) Connect to each device with telnet (usually available in Windows too). The welcome phrase will display the ID assigned in step 1.

  • Perhaps my initial description was not clear enough. I'm not particularly looking for a way of identifying the Pi's. I already have that covered. What I'm looking for is to run one or more bash commands by altering the /boot/cmdline.txt file. This all without the need of logging in via ssh - even once. – EDP Aug 3 '15 at 4:57
  • You probably won't be able to 'ping the subnet broadcast address', Smurf Attacks are usually prevented. – CrackerJack9 Oct 13 '15 at 14:46

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.