Simple replacement of init to just start console - linux

On a very simple PC, I want to replace Ubuntu 12.04 /sbin/init by the most simple bash script in order to have the very minimum number of running processes. Obviously, no X, no USB, no detection of new hardware, no upgrade, no apt, "nothing", I just need a working console with a DHCP-based Wi-Fi IP address (ssid, passphrase are already stored in /etc/network/interfaces). That's all. Currently, I have tried this in replacement of /sbin/init:
#!/bin/sh
mount -o rw,remount /
mount -t proc none /proc
udevd --daemon
mkdir /run/network
ifup -a &
while [ 1 ]; do
/sbin/getty -8 115200 tty1 vt100
done
It's working as I'm getting an IP address and I can login but:
A) While running shutdown, I get "shutdown: Unable to shutdown system:"
B) control-c is not working in the console
C) After a login, I get: "bash: cannot set terminal process group (-1): Inappropriate ioctl for device"
D) After a login, I get: "bash: no job control in this shell"
Also, I have noticed that all the user-space processes have a "?" in the tty column when running ps avx. How can I fix those problems? I don't want to use upstart in order to really control what is started on the PC and have the very bare minimum.

I ended up using Busybox init. Great tiny init...

You could leverage runlevels and based on your question runlevel 3 is what you want to use.
If you have some services that you do not wish to start, you could turn them off too for that runlevel.
For booting into runlevel 3, you just append the boot argument to the kernel in your boot loader:
<EXISTING_BOOT_CMD> 3
If your distro uses systemd instead of sysvinit, they are instead called as targets. The equivalent of runlevel 3 in systemd is usually named as multi-user.target
The kernel boot argument you would need to pass in this case is systemd.unit=multi-user.target
<EXISTING_BOOT_CMD> systemd.unit=multi-user.target
An alternative, if you do not want to touch the boot loader:
systemctl enable multi-user.target

Related

Two xwin-xdg-menu processes with high CPU consumption

I have a Windows 7 computer with intel i7 with 2 cores and hyperthreading and a linux virtual machine in a cloud. I don't like VNC (it's laggy) so I use X windowing.
I start my Cygwin XWin with the following command:
C:\cygwin64\bin\run.exe --quote /usr/bin/bash.exe -l -c "cd; /usr/bin/xinit /etc/X11/xinit/startxwinrc -- /usr/bin/XWin :0 -multiwindow -listen tcp"
It's working otherwise just as intended but for some reason it's spawning two xwin-xdg-menu processes of which the other one is consuming 25% of my CPU. When I kill it, the CPU usage returns to normal and everything is working fine, including the other xwin-xdg-menu process.
I tried also this:
C:\cygwin64\bin\XWin.exe :0 -multiwindow -listen tcp
but it makes the application run slowly and with a bad resolution.
Is there a way to start X with listen-tcp with an adapted resolution to my multiple screens I have and without having to manually kill the extra process every time?
It seems I'm not the only one with this problem but for now I haven't found any solution to this.
https://cygwin.com/ml/cygwin/2017-05/msg00345.html
https://superuser.com/questions/1210325/cygwin-at-spi-bus-launcher-and-xwin-xdg-menu-high-cpu (I don't have problems with at-spi-bus-launcher though)
Solution:
Create a ~/.startxwinrc file, and add one line:
exec sleep infinity
Make ~/.startxwinrc executable by running chmod +x ~/.startxwinrc.
Reason I suspect this worked:
startxwin searches for a ~/.startxwinrc file to execute when launching. If startxwin does not find a ~/.startxwinrc file, startxwin will follow the default routine outlined in /etc/X11/xinit/startxwinrc.
The default routine launches /usr/bin/xwin-xdg-menu, somehow causing me to have two xwin-xdg-menu processes, one of them with very high cpu. Creating ~/.startxwinrc bypasses the default routine, disabling /usr/bin/xwin-xdg-menu from launching altogether.
exec sleep infinity keeps the x server alive after launching.

How to start vlc-nox via ssh in a Linux server running in text mode?

Background
I have a Linux server running in text mode with no X installed. I intend to show video and image using directfb to the monitor (actually a TV). I have installed vlc-nox and it runs as expected if it is invoked in default console (physical keyboard).
Issue
When running it via SSH, no video is displayed, but audio is okay. The error is as below:
directfb vout display error: Cannot create primary surface
fb vout display error: cannot get terminal mode (Inappropriate ioctl for device)
core video output error: video output creation failed
core decoder error: failed to create video output
fbi's way
I think fbi also facing the same issue, as it would raise an error like below:
ioctl VT_GETSTATE: Inappropriate ioctl for device (not a linux console?)
But, fbi provides a solution for this case: -T -vt <arg> start on virtual console <arg>
So, sudo fbi -T 1 /path/to/image/file would display image as expected.
Question: What's the vlc's way?
I finally have a solution for this, so I post it here in case someone has the same question.
My understanding is that vlc needs to run under a real tty, not a pseudo tty. My solution is composed of two parts.
Part 1: Let vlc run as daemon mode.
Create a user for the daemon and assign audio and video privilege.
#useradd -c "VLC daemon" -d / -G audio,video -M -p \! -r -s /bin/false -u 75 -U vlcd
Run vlc at startup using tty1
I have tried this with unit under ubuntu.
[Unit]
Description=VLC server
After=network.target auditd.service
Conflicts=getty#tty1.service
[Service]
ExecStart=/usr/bin/vlc -I rc --rc-host 127.0.0.1:8080
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartPreventExitStatus=255
User=vlcd
Type=simple
#StandardError=tty
StandardOutput=tty
StandardInput=tty
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Alias=vlc.service
Please take notic of the Conflicts, ExecStart, StandardInput, and StandardOutput parts.
In Conflicts, it will bypass the default getty service, otherwise it should be disable manually by #systemctrl disable getty#tty1.
In ExecStart, do not use the -d switch, which meaning that it would keep running and occupying VT 1, which is activated by Alt-F1. -rc enables the remote connect interface.
In StandardInput/Output, specify the tty as input and output device.
Part 2: Remote talk with the daemon, to let it play the file.
As --rc-host specify a local port, we need to ssh to the server first. Then, use telnet to interact (add, play, pause) with vlc.
telnet 127.0.0.1 8080
add /path/to/video/file

mount fails from spawned process

I want to start a process that uses a USB hard drive once it gets inserted.
Since UDEV rules specifically mentions not to run long-time processes from RUN command, I send a FIFO message to my service which then opens the relevant process.
So the flow goes like this:
UDEV > runs action process > sends FIFO message to service > service gets message > runs the process who works with the HDD (aka HDD-PROCESS).
If I run my service from shell-1 and run 'action process' (the one that UDEV runs) from shell-2 everything works (including when trying it with udev).
But in deployment, the service is spawned from init, and when it does, the mount command fails saying "No such device".
I then detached "HDD-PROCESS" with fork and setsid, but that didn't help either.
from inittab:
::respawn:/opt/spwn_frm_init
ps relevant output:
PID PPID PGID SID COMM ARGS
31112 1 31112 31112 spwn_frm_init /bin/sh /opt/spwn_frm_init
31113 31112 31112 31112 runSvc /bin/sh /app/sys/runSvc
31114 31113 31112 31112 python python /app/sys/mainSvc.py
24064 1 24064 24064 python /usr/bin/python /app/sys/hdd_proc.py sdb1
everything runs under root (ps shows that too, I omitted that to save screen space).
So in short: when I run /opt/spwn_frm_init from shell, everything works. when I kill it and let it re-spawn from inittab, it doesn't and mount fails with error above.
UPDATE:
There is no problem when trying to mount an ext3 drive, but only on the NTFS one (using ntfs-3g).
Found it!
One of the differences between spawned process and another one who runs from shell is the environment variables which usually should be a problem when all I want is to call mount.
But when I noticed the problem happens only with the NTFS drive, it suddenly occurred to me that mount might need to call ntfs-3g so it worth checking if the second is accessible in the PATH variable.
which ntfs-3g led to /usr/local/bin/ntfs-3g which was mentioned in the default shell PATH but not in the one spawned from init.
To solve it, I added this /usr/local/bin to PATH in the "HDD-PROCESS" and mount began to work :)
A better error message in mount could have saved a lot of time here...

RPI Not Booting because of infinite shell script

so today i was trying to get a shell script(which is an infinite loop) to run on boot in the background of my RaspberryPi's terminal.
I used this command: update-rc.d -f GPIOServer.sh start 4
and then rebooted my pi and after a couple seconds it runs the infinite loop and doesn't boot to the terminal.
i don't know how to cancel the script: ive tried ^C ^Z ^X Esc and i dont want to have to erase all my files etc.
Please help.
There are several options to get a shell without completing the full boot process:
Try switching to a different console for example with CTRL+ALT+F2 (or any other F2-12 key). This will only work if your init script is one of the last scripts to start.
If the ssh server started before your script then you will be able to connect remotely from another computer
Follow Ignacio's recommendation: by taking out the SD card and mounting the SD card on another linux computer and deleting your init script
If you only have a mac or windows machine then you will only be able to edit the boot parition of the SD card. In this case you can modify/add the boot config file cmdline.txt to boot straight into a root terminal. If there is already a cmdline.txt file on the the sd-card then make a backup copy of this file and then simply add init=/bin/bash after the root kernel parameter.
For example, the full line might look something like this:
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p3 init=/bin/bash rootfstype=ext4 elevator=deadline rootwait
If there is no cmdline.txt file on the sd-card then create a new empty text file and just put init=/bin/bash into that file. Your raspberry pi will now boot straight into a root terminal.
Assuming you are not logging in as root. You can try to log in as root and disable the infinite loop for your user's shell.

Script not starting on boot with start-stop-daemon

My script (located in /etc/init.d) is creating a pid file ($PIDFILE), but there is no process running. My daemon script includes:
start-stop-daemon --start --quiet --pidfile $PIDFILE -m -b --startas $DAEMON --test > /dev/null || return 1
The script works fine when executing it manually.
You need to create startup links.
sudo update-rc.d SCRIPT_NAME defaults
then reboot. SCRIPT_NAME is the name of the script in /etc/init.d (Without the path)
Was able to get it working, but tried so many things, don't know exactly what fixed it (probably an error in script or config). However, learned a lot and wanted to share since I can't find much of the same in the internet abyss.
It seems Ubuntu (and many other distros based on Ubuntu, including Mint) has migrated to Upstart for job and service management. Upstart includes SysVinit (using /etc/init.d daemons) compatibility that still can use update-rc.d to manage daemons (so if you are familiar with that usage, you can keep on using it). The Upstart method is to use a single .conf file in the /etc/init folder. My SCRIPT.conf file is very simple (I'm using a python script):
start on filesystem or runlevel [2345]
stop on runlevel [016]
exec python /usr/share/python-support/SCRIPT/SCRIPT.py
This simple file completely replaces the standard script in /etc/init.d with the case statement to provide [start|stop|restart|reload] functions and the pointer to /usr/bin/SCRIPT. You can see that it includes runlevel control that would normally be found in the /etc/rc*.d files (thus eliminating several files).
I tried update-rc.d to create the necessary /etc/rc*.d/ files for my daemon. My daemon bash script is located in /etc/init.d and includes the start-stop-daemon command as in my original question. (That command also works fine from terminal.)
I had /etc/rc*.d/ files, the bash script in /etc/init.d and /etc/init/SCRIPT.conf file during boot and it seems that Upstart likely first looks for the .conf file for its direction because the SysVinit command service SCRIPT [start|stop|restart|reload] returns Unknown Instance, however you can find the process is running with ps -elf | grep SCRIPT_FILE.
One interesting thing to note is the forking of your daemon when using .conf. The script as written above only spawns one fork of the daemon. However, total independence of the original script is possible by using expect fork or expect daemon and respawn (see the Upstart Cookbook for reference). Using these will ensure that your daemon will never be killed (at least by using the kill command).
I continued to test both my daemon and the boot process by utilizing the sudo initctl reload-configuration command. This reloads the conf files where you can test your daemon by the sudo [start|stop|restart] SCRIPT command. The result of the start command is:
$ sudo start SCRIPT
SCRIPT start/running, process xxxx
$ sudo restart SCRIPT
SCRIPT start/running, process xxxx
$ sudo stop SCRIPT
SCRIPT stop/waiting
Also, there is a nice log in /var/log/upstart/SCRIPT.log that gives you useful information for your daemon during boot. Mine still has a very annoying bug that prevents root from displaying osd messages with notify-send from my daemon. My log file includes a gtk warning (I will open another question to solicit help).
Hope this helps others in developing their daemons.

Resources