Short Description:
I want to auto-start an executable (opencv binary file, generate via c++) via a systemd service-script after booting, but I am unsuccessful.
I narrowed down the error to the code statement "cv::imshow(....)" which opens a window and displays an image. At this point, the code throws the error: "QXcbConnection: Could not connect to display"
However, if I manually execute the sh-script or the binary, both work fine. I searched around stackoverflow for the most common errors, and I tried to fix all I could found. I am quite sure, that:
My service file actually runs at start (until the error occurred)
Manually execution of the binary file works fine
Manually execution of the .sh-script works fine
I do not have runtime-linking errors (see .sh-script)
I would appreciate any help. Please help me fix the error, and please explain to me, why this error even occurs in the first place. Thanks a lot :)
.
My system:
Machine: Raspberry Pi 3 Model B
Architecture: arm32 / ARMv7
OS: NOOBS
.
My script in /etc/systemd/system/ (test.service):
[Unit]
Description=lalala
[Service]
Type=oneshot
ExecStart=/bin/bash "/home/pi/Desktop/test.sh" start
ExecStop=/bin/bash "/home/pi/Desktop/test.sh" stop
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Moreover, I did execute the following commands:
sudo chmod u+rwx /etc/systemd/system/test.service
sudo systemctl enable test
And if I start the service manually, it runs with the same error output as while autostarting during the boot process:
sudo systemctl enable test
.
My shell script (test.sh):
#!/bin/sh -e
exec 2> /tmp/test.sh.log # send stderr to a log file
exec 1>&2 # send stdout to the same log file
set -x # tell sh to display commands before execution
echo "in script"
start()
{
echo "in start"
sleep 30
LD_LIBRARY_PATH=/usr/local/OpenCV/lib:/usr/local/SFML/lib:/usr/local/curl/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH
/home/pi/Desktop/test/main -e &
}
# THE OTHER CASES, NOT PUT IN HERE (stop, status)
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
restart)
stop
start
;;
*)
echo "Usage: {start|stop|status|restart}"
exit 1
;;
esac
exit 0
.
Minimal example of my source code: (executable)
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
int main()
{
cv::Mat frame;
cv::namedWindow("result", cv::WINDOW_NORMAL);
## CRASH
return 0;
}
.
P.S:
I am aware that there is a similar thread like this (Run OpenCV script on start with imshow). But as there is no solution for this question, and as I have more information to share, I thought it would be more appropriate to start a new thread.
Luckily, I solved the problem:
The problem was in the configuration of my serviced-script. I did know that I need a DISPLAY variable to the location of the X Display, but I was not aware of the fact that it needs authorization as well. This thread helped me figure it out:
https://unix.stackexchange.com/questions/85244/setting-display-in-systemd-service-file
In short:
Add these to lines to test.service in /etc/serviced/service:
Environment=XAUTHORITY=/home/pi/.Xauthority
Environment=DISPLAY=:0.0
[Unit]
Description=lalala
[Service]
Type=oneshot
ExecStart=/bin/bash "/home/pi/Desktop/test.sh" start
ExecStop=/bin/bash "/home/pi/Desktop/test.sh" stop
RemainAfterExit=yes
Environment=XAUTHORITY=/home/pi/.Xauthority
Environment=DISPLAY=:0.0
[Install]
WantedBy=multi-user.target
Full code
Related
I have a problem running a .sh script inside a docker container. It gives me:
ml_1 | 2018-08-02 08:31:32,680 INFO spawned: 'datagrid'
with pid 18
ml_1 | 2018-08-02 08:31:32,686 INFO exited: datagrid
(exit status 127; not expected)
ml_1 | 2018-08-02 08:31:38,732 INFO gave up: datagrid
entered FATAL state, too many start retries too quickly
My script:
#!/bin/bash
# Description:
LIB=/home/com/com_server/lib
CONFIG=/home/com/com_server/config
JAVA="/usr/bin/java"
CLASSPATH=${CONFIG}:blackBoard.xml:${CONFIG}:hazelcastContext.xml:${CONFIG}:comAppConfig.xml:${LIB}:com-calc-0.0.1.jar:${LIB}:com-common-0.0.1.jar:${LIB}:com-hazelcast-0.0.1-jar-with-dependencies.jar:${LIB}:escomled-server-0.0.1.jar:${LIB}:spring-webmvc-4.3.0.RELEASE.jar:${LIB}:spring-jdbc-4.3.0.RELEASE.jar:${LIB}:spring-context-4.3.0.RELEASE.jar:${LIB}:hazelcast-spring-3.7.2.jar:${LIB}:hazelcast-client-3.8.3.jar:${LIB}:hazelcast-spring-3.8.3.jar:${LIB}:hazelcast-all-3.8.3.jar:${LIB}:hazelcast-3.8.3.jar:${LIB}:spring-core-4.3.0.RELEASE.jar:${LIB}:spring-beans-4.3.0.RELEASE.jar:${LIB}:log4j-1.2.16.jar:${LIB}:commons-logging-1.2.jar:${LIB}:spring-asm-4.3.0.RELEASE.jar:${LIB}:spring-expression-4.3.0.RELEASE.jar:${LIB}:mysql-connector-java-5.1.34.jar:${LIB}:spring-tx-4.3.0.RELEASE.jar:${LIB}:commons-lang-2.6.jar:${LIB}:mail-1.4.1.jar:${LIB}:commons-digester-2.0.jar:${LIB}:commons-codec-1.4.jar:${LIB}:slf4j-log4j12-1.5.10.jar:${LIB}:slf4j-api-1.5.10.jar:${LIB}:config/createClient.sql:${LIB}:commons-fileupload-1.2.jar:${LIB}:commons-io-1.4.jar:${LIB}:spring-web-4.3.0.RELEASE.jar:${LIB}:opencsv-2.3.jar:${LIB}:spring-aop-4.3.0.RELEASE.jar:${LIB}:aopalliance-1.0.jar:${LIB}:pdfbox-1.8.9.jar:${LIB}:fontbox-1.8.9.jar:${LIB}:jempbox-1.8.9.jar:${LIB}:imgscalr-lib-4.2.jar:${LIB}:dom4j-1.6.1.jar:${LIB}:xmlbeans-2.6.0.jar:${LIB}:jasypt-1.9.2.jar:${LIB}:jackson-mapper-asl-1.9.4.jar:${LIB}:jackson-core-asl-1.9.4.jar:${LIB}:jackson-jaxrs-1.9.4.jar:${LIB}:cglib-2.2.2.jar:${LIB}:asm-3.3.1.jar:${LIB}:textmagic-java-sdk-1.2.0.jar:${LIB}:httpclient-4.5.5.jar:${LIB}:commons-dbcp2-2.3.0.jar:${LIB}:commons-pool2-2.5.0.jar:${LIB}:poi-3.17.jar:${LIB}:poi-ooxml-3.17.jar:${LIB}:commons-collections4-4.1.jar:${LIB}:poi-ooxml-schemas-3.17.jar
SERVER_NAME="com_datagrid"
SLOG_NAME="com_datagrid"
PID_FILE="/var/run/${SLOG_NAME}.pid"
MEMORY="512";
ARGS="-Djava.awt.headless=true -Xmx1024M -Dcom.sun.management.jmxremote=true \
-Dcom.sun.management.jmxremote.port=9092 \
-Dcom.sun.management.jmxremote.ssl=false \
-Dcom.sun.management.jmxremote.authenticate=false \
-Djava.rmi.server.hostname=10.72.4.13 -Dhazelcast.diagnostics.enabled=true -Dhazelcast.diagnostics.metric.level=info -Dhazelcast.diagnostics.invocation.sample.period.seconds=30 -Dhazelcast.diagnostics.pending.invocations.period.seconds=30 -Dhazelcast.diagnostics.slowoperations.period.seconds=30"
start() {
tput setaf 2;echo "---- STARTING *** com_datagrid *** DAEMON ----"
${JAVA} ${ARGS} -classpath "${CLASSPATH}" com.com.blackboard.main.Server &
javaPID=$!
tput setaf 7;echo "*** com_datagrid *** backgrounded with process id '${javaPID}'"
#echo ${javaPID} > ${PID_FILE}
}
stop() {
echo "STOPING *** com_datagrid ***"
start-stop-daemon --stop \
--pidfile ${PID_FILE}
}
restart() {
stop
start
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
esac
exit 0;
My Dockerfile:
#FROM maven:3.3.9-jdk-8-alpine as build-env
#COPY . /comML
#WORKDIR comML
#RUN mvn package
FROM openjdk:8-jdk-alpine
WORKDIR /comML
ADD . /comML
ADD ./MLScripts/lib comML/lib
ADD ./MLScripts/config com/config
ADD ./MLScripts/config com/home/com/com_server/config
ADD ./MLScripts comML/MLScripts
ADD target/com-machine-learning-0.0.1-SNAPSHOT-jar-with-dependencies.jar comML/lib/com-machine-learning-0.0.1-SNAPSHOT-jar-with-dependencies.jar
COPY ./MLScripts/wrapper.sh /com/MLScripts/wrapper.sh
#CMD ["export", "CLASSPATH=comML/home/com/com_server/config/blackBoard.xml;EscomledML/home/com/com_server/config/appContext.xml;comML/home/com/com_server/config/config.properties;comML/home/com/com_server/config/com.properties;comML/home/com/escomled_server/config/createClient.sql;EscomledML/home/escomled/escomled_server/config/escomled.properties;com/home/com/com_server/config/global_database.sql;comML/home/com/com_server/config/release.sql;comML/home/escomled/com_server/config/taskExecutors.xml;comML/home/com/com_server/config/test-applicationContext.xml;C:/home/com/com_server/lib/spring-jdbc-4.3.0.RELEASE.jar;C:/home/escomled/escomled_server/lib/escomled-common-0.0.1.jar;C:/home/escomled/escomled_server/lib/escomled-machine-learning-0.0.1-SNAPSHOT-jar-with-dependencies.jar;C:/home/escomled/escomled_server/lib/assertj-core-3.3.0.jar;C:/home/escomled/escomled_server/lib/curator-test-2.9.0.jar;C:/home/escomled/escomled_server/lib/h2o-genmodel-3.18.0.1.jar;C:/home/escomled/escomled_server/lib/hazelcast-all-3.8.3.jar;C:/home/escomled/escomled_server/lib/jcl-over-slf4j-1.7.1.jar;C:/home/escomled/escomled_server/lib/junit-4.12.jar;C:/home/escomled/escomled_server/lib/spring-jdbc-4.3.0.RELEASE.jar;C:/home/escomled/escomled_server/lib/spring-dao-2.0.3.jar;C:/home/escomled/escomled_server/lib/kafka_2.11-0.10.2.1-cp1.jar;C:/home/escomled/escomled_server/lib/kafka_2.11-0.10.2.1-cp1-test.jar;C:/home/escomled/escomled_server/lib/kafka-clients-0.10.2.1-cp1.jar;C:/home/escomled/escomled_server/lib/spring-context-4.3.0.RELEASE.jar;C:/home/escomled/escomled_server/lib/spring-core-4.3.0.RELEASE.jar;C:/home/escomled/escomled_server/lib/spring-tx-4.3.0.RELEASE.jar;C:/home/escomled/escomled_server/lib/hazelcast-all-3.8.3.jar;C:/home/escomled/escomled_server/lib/kafka-clients-0.10.2.1-cp1-test.jar;C:/home/escomled/escomled_server/lib/kafka-schema-registry-3.2.1.jar;C:/home/escomled/escomled_server/lib/kafka-schema-registry-3.2.1-tests.jar;C:/home/escomled/escomled_server/lib/kafka-streams-0.10.2.1-cp1.jar;C:/home/escomled/escomled_server/lib/slf4j-api-1.7.1.jar;C:/home/escomled/escomled_server/lib/slf4j-log4j12-1.7.1.jar"]
#ENTRYPOINT ["java", "-cp", "EscomledML/home/escomled/escomled_server/config/blackBoard.xml;EscomledML/home/escomled/escomled_server/config/appContext.xml;EscomledML/home/escomled/escomled_server/config/config.properties;EscomledML/home/escomled/escomled_server/config/escomled.properties;EscomledML/home/escomled/escomled_server/config/createClient.sql;EscomledML/home/escomled/escomled_server/config/escomled.properties;EscomledML/home/escomled/escomled_server/config/global_database.sql;EscomledML/home/escomled/escomled_server/config/release.sql;EscomledML/home/escomled/escomled_server/config/taskExecutors.xml;EscomledML/home/escomled/escomled_server/config/test-applicationContext.xml;C:/home/escomled/escomled_server/lib/spring-jdbc-4.3.0.RELEASE.jar;C:/home/escomled/escomled_server/lib/escomled-common-0.0.1.jar;C:/home/escomled/escomled_server/lib/escomled-machine-learning-0.0.1-SNAPSHOT-jar-with-dependencies.jar;C:/home/escomled/escomled_server/lib/assertj-core-3.3.0.jar;C:/home/escomled/escomled_server/lib/curator-test-2.9.0.jar;C:/home/escomled/escomled_server/lib/h2o-genmodel-3.18.0.1.jar;C:/home/escomled/escomled_server/lib/hazelcast-all-3.8.3.jar;C:/home/escomled/escomled_server/lib/jcl-over-slf4j-1.7.1.jar;C:/home/escomled/escomled_server/lib/junit-4.12.jar;C:/home/escomled/escomled_server/lib/spring-jdbc-4.3.0.RELEASE.jar;C:/home/escomled/escomled_server/lib/spring-dao-2.0.3.jar;C:/home/escomled/escomled_server/lib/kafka_2.11-0.10.2.1-cp1.jar;C:/home/escomled/escomled_server/lib/kafka_2.11-0.10.2.1-cp1-test.jar;C:/home/escomled/escomled_server/lib/kafka-clients-0.10.2.1-cp1.jar;C:/home/escomled/escomled_server/lib/spring-context-4.3.0.RELEASE.jar;C:/home/escomled/escomled_server/lib/spring-core-4.3.0.RELEASE.jar;C:/home/escomled/escomled_server/lib/spring-tx-4.3.0.RELEASE.jar;C:/home/escomled/escomled_server/lib/hazelcast-all-3.8.3.jar;C:/home/escomled/escomled_server/lib/kafka-clients-0.10.2.1-cp1-test.jar;C:/home/escomled/escomled_server/lib/kafka-schema-registry-3.2.1.jar;C:/home/escomled/escomled_server/lib/kafka-schema-registry-3.2.1-tests.jar;C:/home/escomled/escomled_server/lib/kafka-streams-0.10.2.1-cp1.jar;C:/home/escomled/escomled_server/lib/slf4j-api-1.7.1.jar;C:/home/escomled/escomled_server/lib/slf4j-log4j12-1.7.1.jar", "com.escomled.machinelearning.ml.Escomled_Streams_H2O_ML"]
#CMD ["java", "-jar", "escomled-machine-learning-0.0.1-SNAPSHOT-jar-with-dependencies.jar"]
EXPOSE 8085
#ENTRYPOINT ["sh", "EscomledML/MLScripts/wrapper.sh"]
#ENTRYPOINT ["sh", "EscomledML/MLScripts/escomled_data_grid.sh"]
#CMD ["sh", "EscomledML/MLScripts/escomled_dirwatcher.sh", "&&", "sh", "EscomledML/MLScripts/escomled_startmap.sh", "&&", "sh", "EscomledML/MLScripts/escomled_ml.sh"]
FROM ubuntu:14.04
RUN apt-get update && apt-get install -y supervisor
RUN mkdir -p /var/log/supervisor
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
CMD /usr/bin/supervisord -n
And my .bat script:
set LIB=C:/home/escomled/escomled_server/lib
set CONFIG=C:/home/escomled/escomled_server/config
set JAVA_HOME="C:\Program Files\Java\jdk1.8.0_144"
set CLASSPATH=%CONFIG%/blackBoard.xml;%CONFIG%/hazelcastContext.xml;%CONFIG%/escomledAppConfig.xml;%LIB%/escomled-calc-0.0.1.jar;%LIB%/escomled-common-0.0.1.jar;%LIB%/escomled-hazelcast-0.0.1-jar-with-dependencies.jar;%LIB%/escomled-server-0.0.1.jar;%LIB%/spring-webmvc-4.3.0.RELEASE.jar;%LIB%/spring-jdbc-4.3.0.RELEASE.jar;%LIB%/spring-context-4.3.0.RELEASE.jar;%LIB%/hazelcast-spring-3.7.2.jar;%LIB%/hazelcast-client-3.8.3.jar;%LIB%/hazelcast-spring-3.8.3.jar;%LIB%/hazelcast-all-3.8.3.jar;%LIB%/hazelcast-3.8.3.jar;%LIB%/spring-core-4.3.0.RELEASE.jar;%LIB%/spring-beans-4.3.0.RELEASE.jar;%LIB%/log4j-1.2.16.jar;%LIB%/commons-logging-1.2.jar;%LIB%/spring-asm-4.3.0.RELEASE.jar;%LIB%/spring-expression-4.3.0.RELEASE.jar;%LIB%/mysql-connector-java-5.1.34.jar;%LIB%/spring-tx-4.3.0.RELEASE.jar;%LIB%/commons-lang-2.6.jar;%LIB%/mail-1.4.1.jar;%LIB%/commons-digester-2.0.jar;%LIB%/commons-codec-1.4.jar;%LIB%/slf4j-log4j12-1.5.10.jar;%LIB%/slf4j-api-1.5.10.jar;%LIB%/config/createClient.sql;%LIB%/commons-fileupload-1.2.jar;%LIB%/commons-io-1.4.jar;%LIB%/spring-web-4.3.0.RELEASE.jar;%LIB%/opencsv-2.3.jar;%LIB%/spring-aop-4.3.0.RELEASE.jar;%LIB%/aopalliance-1.0.jar;%LIB%/pdfbox-1.8.9.jar;%LIB%/fontbox-1.8.9.jar;%LIB%/jempbox-1.8.9.jar;%LIB%/imgscalr-lib-4.2.jar;%LIB%/dom4j-1.6.1.jar;%LIB%/xmlbeans-2.6.0.jar;%LIB%/jasypt-1.9.2.jar;%LIB%/jackson-mapper-asl-1.9.4.jar;%LIB%/jackson-core-asl-1.9.4.jar;%LIB%/jackson-jaxrs-1.9.4.jar;%LIB%/cglib-2.2.2.jar;%LIB%/asm-3.3.1.jar;%LIB%/textmagic-java-sdk-1.2.0.jar;%LIB%/httpclient-4.5.5.jar;%LIB%/commons-dbcp2-2.3.0.jar;%LIB%/commons-pool2-2.5.0.jar;%LIB%/poi-3.17.jar;%LIB%/poi-ooxml-3.17.jar;%LIB%/commons-collections4-4.1.jar;%LIB%/poi-ooxml-schemas-3.17.jar
set SERVER_NAME="escomled_server"
set SLOG_NAME="escomled_server"
set PID_FILE="/var/run/%SLOG_NAME%.pid"
set MEMORY="512";
set ARGS="-Djava.awt.headless=true -Xmx1024M -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=9092 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=10.72.4.13 -Dhazelcast.diagnostics.enabled=true -Dhazelcast.diagnostics.metric.level=info -Dhazelcast.diagnostics.invocation.sample.period.seconds=30 -Dhazelcast.diagnostics.pending.invocations.period.seconds=30 -Dhazelcast.diagnostics.slowoperations.period.seconds=30"
:start
ECHO "---- STARTING *** DataGrid *** DAEMON ----"
%JAVA_HOME%\bin\java.exe %ARGS% -classpath %CLASSPATH% com.escomled.blackboard.main.DataGridServer
ECHO "*** DataGrid *** backgrounded with process id %javaPID%"
ECHO %javaPID% > %PID_FILE%
EXIT /B 0
:stop
ECHO "STOPING *** DataGrid ***"
start-stop-daemon --stop --pidfile %PID_FILE%
EXIT /B 0
:restart
CALL :stop
CALL :start
rem case "$1" in
rem start)
rem start
rem ;;
rem stop)
rem stop
rem ;;
rem restart)
rem stop
rem start
rem ;;
rem esac
rem exit 0;
I will edit the question if I didn't explain something right. Thank you.
I have a problem running a .sh script inside a docker container
You have a number of issues here... Just some pointers:
Your config file structure is a bit messy, from Dockerfile:
WORKDIR /EscomledML
ADD . /EscomledML
ADD ./MLScripts/lib EscomledML/lib
ADD ./MLScripts/config EscomledML/config
ADD ./MLScripts/config EscomledML/home/escomled/escomled_server/config
ADD ./MLScripts EscomledML/MLScripts
won't really be targeted properly by script since it is expecting it elsewhere:
LIB=/home/escomled/escomled_server/lib
CONFIG=/home/escomled/escomled_server/config
Check all file locations to confirm they are properly placed where they should be.
Daemon should be started in foreground as main process. Since you have issues starting process in the first place, try starting container interactively with /bin/bash and hammer out the starting script properly before setting it as entrypoint of Dockerfile.
You are trying to move from one OS to another. Installation details and environment differences can be the cause of your app not starting properly.
You can use build args and env variables directly with docker to avoid initializing them inside script. Make sure that all env vars are properly initialized
Edit after comment:
You are also having issues with multistage build... Artifacts from previous stage you don't transfer to the last one, effectively dumping them. That's why you don't have any folder after last stage. You need something to the effect of COPY --from=0 ... and also check your desired outcome, since you might be misusing multistage build here (primary intent is to build something in previous layer as disposable build stage, not to combine two images into one).
Edit after next comment:
The way I see it, only thing you are using ubuntu image is to install supervisord. If that is the case, then simply replacing following lines:
FROM ubuntu:14.04
RUN apt-get update && apt-get install -y supervisor
with:
apk add --update supervisor
Will install supervisord in alpine image and you would be good to go.
Note that your directory structure looks quite messed up (you first ADD . then subfolders etc) so make sure to review those things. I have no idea what is your desired directory structure, but you should be able to make head or tails there...
To a first approximation, commands that launch system services or background processes (service, systemctl, initctl, start-stop-daemon, ...) just don't work in Docker.
If you replace all of your script after the initial environment variable setup with the command that runs the actual server in the foreground
#!/bin/sh
LIB=...
...
ARGS=...
exec ${JAVA} ${ARGS} -classpath "${CLASSPATH}" com.escomled.blackboard.main.DataGridServer
The Docker container will stay running until that server process exits, which is what you usually want.
I have a really huge archive, which must be extracted file by file and further processed. I don't have enough memory to extract the whole archive (neither in RAM nor on the flash) - thus I wrote a small application which stops (raise(SIGSTOP)) after each extracted file. An equivalent could be this code:
#include <stdio.h>
#include <signal.h>
int main() {
printf("started.\n"); fflush(stdout);
sleep(2); // extracting archive
printf("stopping\n"); fflush(stdout);
raise(SIGSTOP); // stopping
printf("resume + done\n"); fflush(stdout);
return 0;
}
This works fine while I execute this in the terminal:
$ gcc -o dosleep main.c
$ ./dosleep
started.
stopping
[1]+ Stopped ./dosleep
$ fg
./dosleep
resume + done
$
But when calling the method from a script, the command never returns:
$ cat doit.sh
#!/bin/sh
echo "STARTING"
./dosleep
echo "BACK"
$ ./doit.sh
STARTING
started.
stopping
^C^C^C^C^C^C
Why do terminal and script behave so differently? Is there a way to change this behavior?
Thanks, Karl
Job control is off-by-default in noninteractive shells, but you can enable it explicitly:
set -m
Thus, if we modify your script to add either the set -m line or a -m on the shebang as follows:
#!/bin/bash -m
./start-delay
echo BACK
...then BACK is emitted after stopping.
Quoting from the bash man page section on set, emphasis added:
-m Monitor mode. Job control is enabled. This option is on by default for interactive shells on systems that support it (see JOB CONTROL above). All processes run in a separate process group. When a background job completes, the shell prints a line containing its exit status.
(Sorry for bad English, I'm German)
I'm trying (without success) to make my own program start automatically after booting (on a raspberry with raspian).
This is my script: (Note: You have to run this program with root privileges) (Note#2: There must be an empty file called "/home/testLog.txt" with write privileges for every user):
rm /etc/init.d/RMStart
echo "
#! /bin/sh
### BEGIN INIT INFO
# Provides: bla1
# Required-Start:
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: bla2
# Description: bla3
### END INIT INFO
#Switch case for the first parameter
case \"\$1\" in
start)
echo \"Start\" >> /home/testLog.txt
echo runlevel >> /home/testLog.txt
;;
stop)
echo \"Stop\" >> /home/testLog.txt
echo runlevel >> /home/testLog.txt
;;
restart)
echo \"Restart\" >> /home/testLog.txt
echo runlevel >> /home/testLog.txt
;;
*)
echo \"something else\" >> /home/testLog.txt
;;
esac
exit 0
" >> /etc/init.d/RMStart
chmod +x /etc/init.d/RMStart
update-rc.d RMStart remove #Remove older versions of this program ... in theory
update-rc.d RMStart defaults #Install new version of this program ... in theory
I've rebooted the raspberry, but the file /home/testLog.txt is still empty.
However, if I run the command: "/etc/init.d/RMStart" or "/etc/init.d/RMStart start" there is a new entry in /home/testLog.txt.
I would be thankful if anyone knows why the file /home/testLog.txt is still empty and how I could fix that.
Update:
I've tried a new installation script:
#RMS install script
chmod +x botComp.sh
rm /home/pi/RMS
pkill RMS
./botComp.sh
cp RMS /home/pi
chmod +x /home/pi/RMS
rm /etc/init.d/startRMS
sudo echo "#!/bin/sh
### BEGIN INIT INFO
# Provides: fqew
# Required-Start:
# Required-Stop:
# Default-Start: 3 4 5
# Default-Stop: 0 1 6
# Short-Description: sfwef
# Description: gfewf
### END INIT INFO
# Actions
case \"\$1\" in
start)
# START
su pi sh -c \" /home/pi/RMS \"
;;
stop)
# STOP
;;
restart)
# RESTART
;;
esac
exit 0 " >> /etc/init.d/startRMS
chmod +x /etc/init.d/startRMS
update-rc.d startRMS remove
update-rc.d startRMS defaults
The only difference I can see is the name of the script (/etc/init.d/startRMS instead of /etc/init.d/RMStart).
The script works, RMS is running.
It's not really a problem, but the script outputs:
insserv: script RMStart: service F already provided!
insserv: script RMStart: service F already provided!
I've added the line system("runlevel >> /home/pi/runlevelLog.txt"); In the program (RMS) but the content of /home/pi/runlevelLog.txt is: "unknown".
Does RMS start at runlevel 3? How I can I verify this? (I think runlevel 3 is ideal, because RMS needs Network Connection.) Thank you for your help.
is /etc/init.d/RMStart definitely being executed on reboot? use ls -lu to check the last time the file was accessed, wait a minute before rebooting, and repeat the command once you're back up. If the access time hasn't moved on then your script isn't being run which would explain the empty file as your script looks Ok.
You should also double check that update-rc.d has created symbolic links to your script in the appropriate run level directives e.g. does /etc/rc2.d/RMStart exist?
Another sanity check would be running your script using the symbolic links in the above directory rather than from /etc/init.d e.g. does /etc/rc2.d/RMStart
generate output in /home/testLog.txt?
Let me know what you find and we'll take it from there.
EDIT: attempting to replicate..
Well I managed to find my PI; the good news is that neither of us are going mad because it worked perfectly first time as we both believed it should.
I took a copy of your file, and I wrote a quick script (x) to check the exit codes from update-rc.d just to make 100% sure it wasn't complaining about anything.
Hopefully you can follow what I did in the screen shot above - I replicated the steps you followed almost exactly with a bit of extra checking along the way. The script certainly works as designed when called directly.
I then rebooted immediately and checked testLog.txt as soon soon as the system was up. You can see two entries in the file which is expected behaviour as init would have run /etc/rc6.d/K01RMStart as the system went down for reboot, and /etc/rc5.d/S01RMStart as it came up again.
Unfortunately this doesn't help you much.....
The only significant differnce between our tests was that I ran everything as root rather than using sudo. This shouldn't make a difference but the next logical thing for you to try is probably copying my test exactly and seeing if it works for you?
Not that this should be at all significant but I'm running Raspbian 8 (kernel 4.1.13+).
EDIT2: awesome... great stuff. I'd still like to know what the problem was but the main thing in that it's working.
System V based distributions will usually start in either level 3 or level 5, the difference being that level 5 will start the GUI whereas level 3 will start in text mode, their default runlevel is controlled by a line in /etc/inittab.
Debian(Raspian) distros are a bit different - (https://www.debian.org/doc/debian-policy/ch-opersys.html#s-sysvinit). They make no distinction between run levels 2-5 and leave it up the user to configure them to suit their requirements by adding services using the mechanism that's been causing us pain for the last 24 hours. They always start in level 5 unless a "init=" kernel boot parameter has been set, which you can do either at boot time or with a tool like bum or raspi-config.
The command runlevel will tell you the current level on raspian.
You can change the runlevel on the fly with telinit new_runlevel if you need to, but whatever you do, don't set the default runlevel to 0 :-)
The short version is:
I have a systemd unit that I want to check the return code of a script when I call:
systemctl status service.service
Long version: I had a lsb init script that did exactly that, when status was passed as parameter it called a script that checked the state of several processes and based on the return code the init system returned the state correctly of the software.
Now when adapting the script to systemd I can't find out how to configure this behaviour.
Short answer
This is impossible in systemd. The systemctl status verb always does the same thing, it cannot be overrided per-unit to a custom action.
Long answer
You can write a foo-status.service unit file with Type=oneshot and ExecStart= pointing to your custom status script, and then run systemctl start foo-status. However, this will only provide a zero/nonzero information (any nonzero exit code will be converted to 1).
To get the real exit code of your status script, run systemctl show -pExecMainStatus foo-status, however, if you go this far, then it is simpler to run your script directly.
You can use:
systemctl show -p ExecMainStatus service.service | sed 's/ExecMainStatus=//g'
This will return the exit code of the service.
If you are in control of the code of the service you start / stop that way, then you can easily edit it and save the result in a file.
Otherwise, you can always add a wrapper that does that for you.
#!/bin/sh
/path/to/service and args here
echo $? >/run/service.result
Then your status can be accessed using the contents of that file:
STATUS=`cat /run/service.result`
if test $STATUS = 1
then
echo "An error occurred..."
fi
(Side note: /run/ is only writable by root, use /tmp/ if you are not root.)
I want to run simple unmount command before starting my "file-system" service on my node.
Is there any way to call bash script as cluster service?
You can run any script as a cluster service. The script needs to be LSB compliant: i.e. needs to know start, stop, restart, status, etc. I usually copy something simple from /etc/init.d and modify it for myself.
Put the script in /etc/ha.d/resource.d
Test it from command line
# sh /etc/ha.d/resource.d/start (see if it unmounts)
Now if you haven't already, create resource group. Add in all your resources into the same group. Then add your new script in the resource group. You can configure constraints so that all resources depend on your first application resource to run first.
That's about it. You don't need to actually have anything configured for stop and status except "exit" since you just want your script to run once (to unmount)
Here is a script that might work in /etc/ha.d/resource.d
#!/bin/sh
#
# description: testapp auto start-stop script.
#
. /etc/rc.status
case "$1" in
start)
umount [filesystem]
;;
stop)
;;
reload*|restart*|force-reload*)
;;
status)
;;
*)
echo "options: start|stop|reload|restart|force-reload|status"
exit 1
;;
esac
exit
Hope that helps
I have an outline of my steps for building clusters plus an ebook here:
http://geekswing.com/geek/building-a-two-node-sles11-sp2-linux-cluster-on-vmware/