how can I make my C code to auto-run on my Raspberry PI? I have seen a tutorial so as to achieve that but I do not really know what I am still missing. My initialization script is shown as it follows:
#! /bin/sh
# /etc/init.d/my_settings
#
# Something that could run always can be written here
### BEGIN INIT INFO
# Provides: my_settings
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# X-Interactive: true
# Short-Description: Script to start C program at boot time
# Description: Enable service provided by my_settings
### END INIT INFO
# Carry out different functions when asked to by the system
case "$1" in
start)
echo "Starting RPi Data Collector Program"
# run application you want to start
sudo /home/pi/Documents/C_Projects/cfor_RPi/charlie &
;;
stop)
echo "Killing RPi Data Collector Program"
# kills the application you want to stop
sudo killall charlie
;;
*)
echo "Usage: /etc/init.d/my_settings {start | stop}"
exit 1
;;
esac
exit 0
The problem is that my program does not run at boot time and I do not really know why. What would I be missing? Is this "killall" statement "killing" some useful process during execution time? I am making this code to run as a background application but I know that after a few seconds, when the RPi is initializing, it asks for an username and a password in order to initialize the session. Is it possible that my RPi is not executing this code because I am not providing the logging information? I do not have a monitor so that my program has to run once I plug my Rpi in. Thanks a lot in advance!!
You'll have to create links to that init script in the proper /etc/rcX.d folders. On raspbian this is done by:
sudo update-rc.d YOUR_INIT_SCRIPT_NAME defaults
You can read this debian how-to for further information. Also you should read more about run levels in Debian.
How scripts/services are run at startuptime, generally depends on the type of init system used. Off the top of my head, I'd distginguish the following 4 types:
Embedded style: A single shell script has all the commands to start the system. Usually the script is at one off the paths the kernel tries to start as init process.
BSD style
System V style: This uses /etc/inittab and latr scripts in /etc/rc*.d/ to start services one by one
systemd
Raspbian dervices from Debian, so I suppose System V style. You have to symlink your script to /etc/rc2.d like
ln -s /etc/init.d/your-script /etc/rc2.d/S08my-script
Not the structure of the link name: It says, it should be started when the run level is entered, and the '08' determines the position (do a ls /etc/rc2.d/ to see the other links).
More details: init(8).
update-rc.d(8) is the proper wway to create the symlinks on debian. See the manpage:
update-rc.d - install and remove System-V style init script links
I advice to read at least the man pages update-rc.d(8) and init(8).
http://www.akeric.com/blog/?p=1976
Here a tutorial on how to auto-loggin and start a script at boot.
If it still don t work, there s either a problem in your script or in your C program.
Related
I'm running GNU - Screen (4.03.01) so I can have multiple terminals in one, and I'm looking for a good way to display live stats of my memory, so as I do things like compiling, testing programs, etc... I can see how much resources I have left.
I know there is "TOP" the performance monitor... and other similar programs, but I'm not looking for the entire active process list etc... I just want a snapshot of my memory stats that updates for example every 3-5 seconds.
I really appreciate anyone taking the time to help me with this, so thank you!
(for visualization purposes)
Screenshot:
You can use the combination of watch which repeats the specified program and displays its output and free which shows current memory usage
watch free -m
free --help
Usage:
free [options]
Options:
-b, --bytes show output in bytes
-k, --kilo show output in kilobytes
-m, --mega show output in megabytes
-g, --giga show output in gigabytes
--tera show output in terabytes
-h, --human show human-readable output
--si use powers of 1000 not 1024
-l, --lohi show detailed low and high memory statistics
-o, --old use old format (without -/+buffers/cache line)
-t, --total show total for RAM + swap
-s N, --seconds N repeat printing every N seconds
-c N, --count N repeat printing N times, then exit
--help display this help and exit
-V, --version output version information and exit
For more details see free(1).
watch --help
Usage:
watch [options] command
Options:
-b, --beep beep if command has a non-zero exit
-c, --color interpret ANSI color sequences
-d, --differences[=]
highlight changes between updates
-e, --errexit exit if command has a non-zero exit
-g, --chgexit exit when output from command changes
-n, --interval seconds to wait between updates
-p, --precise attempt run command in precise intervals
-t, --no-title turn off header
-x, --exec pass command to exec instead of "sh -c"
-h, --help display this help and exit
-v, --version output version information and exit
You could use valgrind tool Massif, I haven't tried it, but it seems to be what you are looking for.
To use massif, install valgrind then run:
valgrind --tool=massif program argument1 argument2 ...
another fast solution is script like this
while true; do
free -m
# any command for CPU stats - i didn't understand - what you really want to see, please clarify - just % of CPU usage ?
# i think this command should help you.
ps -A -o pcpu | tail -n+2 | paste -sd+ | bc
done
The other thing you can do is use htop. It displays memory usage, CPU usage per core and shows resources used by each process. Really neat but maybe not that detailed as the rest of the answers.
I want to make a shell script that keeps running to check if my two light weight web servers are still running, and restart them if one is not.
I can use the the command pgrep -f thin to get an array (?) of pids of my server called thin.
When this returned array has a count of zero I want to run a command which starts both servers:
cd [path_to_app] && bundle exec thin -C app_config.yml start
pgrep -f thin returns all the pids of the servers that are running. For example:
2354223425
I am new to shell scripting and don't know how to store the results of pgrep-f thin in an array. E.g.,
#!/bin/sh
while true
do
arr=$(pgrep -f thin) # /edited and now THIS WORKS!
#Then I want to check the length of the array and when it is empty run the above
#command, e.g.,
if [ ${#arr[#]} == 0 ]; then
cd [path_to_app] && bundle exec thin -C app_config.yml start
fi
#wait a bit before checking again
sleep 30
done
The first problem I have is that I cannot store the pgrep values in an array, and I am not sure if I can check against zero values. After that I am not sure if there are problems with the other code. I hope someone can help me!
You forgot to execute the command:
arr=($(pgrep -f thin))
[...] when it is empty
If you only check for emptyness, you can directly use the exit status of grep.
-q, --quiet, --silent
Quiet; do not write anything to standard output.
Exit immediately with zero status
if any match is found, even if an error was detected.
This is the process we perform manually.
$ sudo su - gvr
[gvr/DB:DEV3FXCU]/home/gvr>
$ ai_dev.env
Gateway DEV3 $
$ gw_report integrations long
report is ******
Now i am attempting to automate this process using a shell script:
#!/bin/ksh
sudo su - gvr
. ai_dev3.env
gw_report integrations long
but this is not working. Getting stuck after entering the env.
Stuck at this place (Gateway DEV3 $)
You're not running the same commands in the two examples - gw_report long != gw_report integrations long. Maybe the latter takes much longer (or hangs).
Also, in the original code you run ai_dev.env and in the second you source it. Any variables set when running a script are gone when returning from that script, so I suspect this accounts for the different behavior.
I have a program in c/gtk which is opened with gksu. The problem is that when I get the environment variable $HOME with getenv("HOME") it returns "root" obviously. I would like to know if there is a way to know who was the user that executed the gksu or the way to get his environmental variables.
Thanks in advance!
See the man page. Use gksu -k command... to preserve the environment (in particular, PATH and HOME).
Or, like Lewis Richard Phillip C indicated, you can use gksu env PATH="$PATH" HOME="$HOME" command... to reset the environment variables for the command. (The logic is that the parent shell, the one run with user privileges, substitutes the variables, and env re-sets them when superuser privileges have been attained.)
If your application should only be run with root privileges, you can write a launcher script -- just like many other applications do. The script itself is basically
#!/bin/sh
exec gksu -k /path/to/your/application "$#"
or
#!/bin/sh
exec gksu env PATH="$PATH" HOME="$HOME" /path/to/your/application "$#"
The script is installed in /usr/bin, and your application as /usr/bin/yourapp-bin or /usr/lib/yourapp/yourapp. The exec means that the command replaces the shell; i.e. nothing after the exec command will ever be executed (unless the application or command cannot be executed at all) -- and most importantly, there will not be an extra shell in memory while your application is begin executed.
While Linux and other POSIX-like systems do have a notion of effective identity (defining the operations an application may do) and real identity (defining the user that is doing the operation), gksu modifies all identities. In particular, while getuid() returns the real user ID for example for set-UID binaries, it will return zero ("root") when gksu is used.
Therefore, the above launch script is the recommended method to solve your problem. It is also a common one; run
file -L /usr/bin/* /usr/sbin/* | sed -ne '/shell/ s|:.*$||p' | xargs -r grep -lie launcher -e '^exec /'
to see which commands are (or declare themselves to be) launcher scripts on your system, or
file -L /bin/* /sbin/* /usr/bin/* /usr/sbin/* | sed -ne '/shell/ s|:.*$||p' | xargs -r grep -lie gksu
to see which ones use gksu explicitly. There is no harm in adopting a known good approach.. ;)
you could assign the values of these environment vars to standard variables, then execute gksu exporting the vars after gkSU... By defining these after the gkSU using && to bind together your executions, so that you essentially execute using cloned environment variables...
A better question is why do this at all? I realize you are wanting to keep some folders, but am not sure why as any files created as root, would have to be globally writable, probably using umask, or you would have to manually revise permissions or change ownership... This is such a bad Idea!
Please check out https://superuser.com/questions/232231/how-do-i-make-sudo-preserve-my-environment-variables , http://www.cyberciti.biz/faq/linux-unix-shell-export-command/ & https://serverfault.com/questions/62178/how-to-specify-roots-environment-variable
I need this cron job to execute my shell just as it does when I run it on the command line.
I read through the one other question I found about this, but my console-based cron job still is not working. I want to post some code and what it outputs, maybe someone can tell me what's going on.
First off, this is on Cake 1.3. I am running on Ubuntu 9.10. I have tried the shell-script method described in the Cake Book.
I have NOT established any special user account for running the script. The cake console is on my PATH (for the ubuntu built-in user).
In another question I found, they report that the -app parameter isn't doing anything. This seems to be the case for me as well.
My shell works as it should when I run this from the command line:
./vendors/cakeshell subscription_reminder -cli /usr/bin -app /var/www/www.example.org/htdocs/app -console /var/www/www.example.org/htdocs/cake/console/cake
the output from this looks like:
Welcome to CakePHP v1.3.2 Console
---------------------------------------------------------------
App : app
Path: /var/www/www.directory.sdcweb.org/htdocs/app
---------------------------------------------------------------
I'm logging my cron-job output to a file and the output of that looks different, like this:
EDIT: i've noticed that this following code block is just the cake shell script that comes with CakePHP, if you open up cake/console/cake in a text editor you should find the following script.
################################################################################
#
# Bake is a shell script for running CakePHP bake script
# PHP versions 4 and 5
#
# CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
# Copyright 2005-2010, Cake Software Foundation, Inc.
#
# Licensed under The MIT License
# Redistributions of files must retain the above copyright notice.
#
# #copyright Copyright 2005-2010, Cake Software Foundation, Inc.
# #link http://cakephp.org CakePHP(tm) Project
# #package cake
# #subpackage cake.cake.console
# #since CakePHP(tm) v 1.2.0.5012
# #license MIT License (http://www.opensource.org/licenses/mit-license.php)
#
################################################################################
LIB=${0/%cake/}
APP=`pwd`
exec php -q ${LIB}cake.php -working "${APP}" "$#"
exit;
My crontab looks like this:
41 20 * * * /var/www/www.example.org/htdocs/app/vendors/cakeshell subscription_reminder -cli /usr/bin -app /var/www/www.example.org/htdocs/app -console /var/www/www.example.org/htdocs/cake/console/cake >> /home/ubuntu/cron-log
First of all, your cronjob runs the script with a different cwd, which may affect behavior. Change it to
41 20 * * * cd /var/www/www.example.org/htdocs/app/; ./vendors/cakeshell ....
But maybe there's something else:
The "cakephp console", cakeshell, probably checks if it's stdin is connected to a tty. If not, it goes in some other, non-interactive mode.
The point is that some programs can talk to you in a terminal (a tty) and others can't.
Some can do both, depending on circumstances.
grep is typically non-interactive
vi, pico and nano are typically only used interactively:
$ vi > test3
Vim: Warning: Output is not to a terminal
$ echo bla | vi
Vim: Warning: Input is not from a terminal
$ vi < test3
Vim: Warning: Input is not from a terminal
bash can do both (non-interactive when running scripts, interactive when serving you in a terminal)
So there's at least the answer as to why the exact same command and environment, can give totally different output. Try to start it from the commandline as you did, but redirecting input from either a pipe or a file, and see what changes.
Well, after a bit more work on this I finally arrived at a crontab which does what I want. It looks like this:
35 01 * * * cd /var/www/www.example.org/htdocs/app; ../cake/console/cake subscription_reminder
Not only does it work, but it is also a lot more readable.
Does your cakeshell begin with
#!/bin/bash
As per the example on http://book.cakephp.org/view/1110/Running-Shells-as-cronjobs?