Linux: setting process priority AND dynamically loading libraries - scheduling

I have a linux application which loads *.so libraries using a modified rpath (set during installation). It also needs to run with realtime priority.
To get realtime priority it does this:
sched_param sched;
sched.sched_priority = 70;
sched_setscheduler(getpid(), SCHED_FIFO, &sched);
However sched_setscheduler is a privilaged method, protected by the CAP_SYS_NICE capability. Therefore, to get realtime priority without running as root, I add setcap to my postinst:
setcap cap_sys_nice+ep /path/to/myapp
However, linux decides that programs should not be allowed to load libraries from rpath if they have extra capabilities.
Is there a way for me to set my own priority and load rpath libraries?
Note: I'd prefer to do this in the application or in the postinst. I'd like to avoid deploying scripts as the only way to launch the application. I know sudo chrt -f -p 70 $! could do it from a script.

I have two solutions which do not involve modifying libc. Both solutions require us to replace the calls to sched_setscheduler() with a call to launch another process directly.
Install a file to /etc/sudoers.d/ with the following line:
%users ALL=NOPASSWD: /usr/bin/chrt
Then from our application launch sudo as a process with arguments chrt -f -p X Y where X is the configured priority and Y is the result of getpid().
Create a custom chrt with:
cp $(which chrt) $(DESTDIR)/bin/chrt
sudo setcap cap_sys_nice+ep $(DESTDIR)/bin/chrt
sudo chmod 755 $(DESTDIR)/bin/chrt
Then from our application launch chrt as a process with arguments -f -p X Y
Not sure which solution is better. Note this is effectively embedded (or at least purpose built) so I'm not too worried about the security exposure.

Related

autostart webserver and programm

I'm working on a Yocto based system. My problem is that I can't start my programm written in C++ and the webserver (node.js) at the same time right after the boot of my device.
I already tried this in /etc/init.d:
#! /bin/bash
/home/ProjectFolder/myProject
cd /home/myapp && DEBUG=myapp:* npm start
exit 0
I changed the rights after creating the script by
chmod +x ./startProg.sh
After that I linked it by
update-rc.d startProg.sh defaults
After reboot the system only starts the C++-programm. I tried some other possibilities like seperating the two comands in different shell-scripts, but that didn't work out any better.
Is there any option I missed or did I make any mistake trying to put those two processes into the autostart?
This of course isn't a C++ or Node.js question. A shell script is a list of commands that are executed in order, unless specified otherwise. So your shell script runs your two programs in the order specified, first myProject and when that's done npm will be started.
This is the same as what would happen from the prompt and the solution is the same: /home/ProjectFolder/myProject &

my system V init script don't return

This is script content, located in /etc/init.d/myserviced:
#!/lib/init/init-d-script
DAEMON="/usr/local/bin/myprogram.py"
NAME="myserviced"
DESC="The description of my service"
When I start the service (either by calling it directly or by calling sudo service myserviced start), I can see program myprogram.py run, but it did not return to command prompt.
I guess there must be something that I misunderstood, so what is it?
The system is Debian, running on a Raspberry Pi.
After more works, I finally solved this issue. There are 2 major reasons:
init-d-script actually calls start-stop-daemon, who don't work well with scripts specified via --exec option. When killing scripts, you should only specify --name option. However, as init-d-script always fill --exec option, it cannot be used with script daemons. I have to write the sysv script by myself.
start-stop-daemon won't magically daemonize the thing you provide. So the executable provided to start-stop-daemon should be daemonized itself, but not a regular program.

Is it possible to watch the ongoing cpu and memory usage of a running C++ app on a server linux distro?

I have developed a c++ app that runs on debian jessie server. Since I'm quite new in linux distros and specially the server ones that provide only terminal, I 'd like to find out if there is a way to watch the %CPU and %MEM on the same time that the c++ app runs. I tried to run
./C++_APP & ps -aux | grep .C++_APP
but ps ran only at the beginning. Is this possible somehow either with ps or with another command?
Use watch. You can pass your ps (along with its arguments) to it. If you don't run your application as a background process you will have to use a second terminal session or pipe the results to a file that you can look at later on.
You can use/install htop.
Set filter to match your executable name.
You may try that:
./C++_APP & wait && PID=`pidof -s -x C++_APP` && top -b -p $PID
It will display stats every second.
To break CTRL+C
To kill your app type than
kill $PID

running parallel code on PC

I have fortran code that has been parallelized with OpenMP. I want to test my code on my PC before running on HPC. My PC has double core CPU and I work on Linux-mint. I installed gfortranmultilib and this is my script:
#!/bin/bash
### Job name
#PBS -N pme
### Keep Output and Error
#PBS -j eo
### Specify the number of nodes and thread (ppn) for your job.
#PBS -l nodes=1:ppn=2
### Switch to the working directory;
cd $PBS_O_WORKDIR
### Run:
OMP_NUM_THREADS=$PBS_NUM_PPN
export OMP_NUM_THREADS
ulimit -s unlimited
./a.out
echo 'done'
What should I do more to run my code?
OK, I changed script as suggested in answers:
#!/bin/bash
### Switch to the working directory;
cd Desktop/test
### Run:
OMP_NUM_THREADS=2
export OMP_NUM_THREADS
ulimit -s unlimited
./a.out
echo 'done'
my code and its executable file are in folder test on Desktop, so:
cd Desktop/test
is this correct?
then I compile my simple code:
implicit none
!$OMP PARALLEL
write(6,*)'hi'
!$OMP END PARALLEL
end
by command:
gfortran -fopenmp test.f
and then run by:
./a.out
but only one "hi" is printed as output. What should I do?
(and a question about this site: in situation like this I should edit my post or just add a comment?)
You don't need and probably don't want to use the script on your PC. Not even to learn how to use such a script, because these scripts are too much connected to the specifics of each supercomputer.
I use several supercomputers/clusters and I cannot just reuse the script from one at the other, because they are so much different.
On your PC you should just do:
optional, it is probably the default
export OMP_NUM_THREADS=2
to set the number of OpenMP threads to 2. Adjust if you need some other number.
cd to the working directory
cd my_working_directory
Your working directory is the directory where you have the required data or where the executable resides. In your case it seems to be the directory where a.out is.
run the damn thing
ulimit -s unlimited
./a.out
That's it.
You can also store the standard output and error output to a file
./out > out.txt 2> err.txt
to mimic the supercomputer behaviour.
The PBS variables are only set when you run the script using qsub. You probably don't have that on your PC and you probably don't want to have it either.
$PBS_O_WORKDIR is the directory where you run the qsub command, unless you set it differently by other means.
$PBS_NUM_PPN is the number you indicated in #PBS -l nodes=1:ppn=2. The queue system reads that and sets this variable for you.
The script you posted is for Portable Batch System (https://en.wikipedia.org/wiki/Portable_Batch_System) queue system. That means, that the job you want to run on the HPC infrastructure has to go first into the queue system and when the resources are available the job will run on the system.
Some of the commands (those starting with #PBS) are specific commands for this queue system. Among these commands, some allow the user to indicate the application process hierarchy (i.e. number of processes and threads). Also, keep in mind that since all the PBS commands start by # they are ignored by regular shell script execution. In the case you presented, that is given by
### Specify the number of nodes and thread (ppn) for your job.
#PBS -l nodes=1:ppn=2
which as the comment indicates it should tell the queue system that you want to run 1 process and each process will have 2 threads. The queue system is likely to pass these parameters to the process launcher (srun/mpirun/aprun/... for MPI apps in addition to OMP_NUM_THREADS for OpenMP apps).
If you want to run this job on a computer that does not have PBS queue, you should be aware at least of two things.
1) The following command
### Switch to the working directory;
cd $PBS_O_WORKDIR
will be translated into "cd" because the environment variable PBS_O_WORKDIR is only defined within the PBS job context. So, you should change this command (or execute another cd command just before the execution) in order to fix where you want to run the job.
2) Similarly for PBS_NUM_PPN environment variable,
OMP_NUM_THREADS=$PBS_NUM_PPN
export OMP_NUM_THREADS
this variable won't be defined if you don't run this within a PBS job context, so you should set OMP_NUM_THREADS to the value you want (2, according to your question) manually.
If you want your linux box environment to be like an HPC login node. You can do the following
Make sure that your compiler supports OpenMP, test a simple hello world program with OpenMP flags
Install OpenMPI on your system from your favourite package manager or download the source/binary from the website (OpenMPI Download)
I would not recommend installing cluster manager like Slurm for your experiments
After you are done, you can execute your MPI programs through the mpirun wrapper
mpirun -n <no_of_cores> <executable>
EDIT:
This is assuming that you are running this only MPI. Note that OpenMP utilizes the cores as well. If you are running MPI+OpenMP - n*OMP_NUM_THREADS=cores on a single node.

How to execute complex linux commands in Qt? [duplicate]

This question already has answers here:
Piping (or command chaining) with QProcess
(5 answers)
Closed 8 years ago.
I want to restart the computer by running a command in linux using QProcess. I have hard-coded my root password in my application.
When i run the following in a terminal it works perfect:
echo myPass | sudo -S shutdown -r now
When i put the command in a shell script and call it via QProcess it is also successful :
QProcess process;
process.startDetached("/bin/sh", QStringList()<< "myScript.sh");
But i can not run it by directly passing to QProcess:
process.startDetached("echo myPass | sudo -S shutdown -r now ");
It will just print myPass | sudo -S shutdown -r now
How is it possible to run such relatively complex commands directly using QProcess. (Not putting in a shell script).
The key methods that exist for this purpose established in QProcess:
void QProcess::setProcessChannelMode(ProcessChannelMode mode)
and
void QProcess::setStandardOutputProcess(QProcess * destination)
Therefore, the following code snippet would be the equivalence of command1 | command2 without limiting yourself to one interpreter or another:
QProcess process1
QProcess process2;
process1.setStandardOutputProcess(&process2);
process1.start("echo myPass");
process2.start("sudo -S shutdown -r now");
process2.setProcessChannelMode(QProcess::ForwardedChannels);
// Wait for it to start
if(!process1.waitForStarted())
return 0;
bool retval = false;
QByteArray buffer;
// To be fair: you only need to wait here for a bit with shutdown,
// but I will still leave the rest here for a generic solution
while ((retval = process2.waitForFinished()));
buffer.append(process2.readAll());
if (!retval) {
qDebug() << "Process 2 error:" << process2.errorString();
return 1;
}
You could drop the sudo -S part because you could run this small program as root, as well as setting up the rights. You could even set setuid or setcap for the shutdown program.
What we usually do when building commercial Linux systems is to have a minimal application that can get setuid or setcap for the activity it is trying to do, and then we call that explicitly with system(3) or QProcess on Linux. Basically,
I would write that small application to avoid giving full root access to the whole application, so to restrict the access right against malicious use as follows:
sudo chmod u+s /path/to/my/application
First, you could configure sudo to avoid asking you the password. For instance by being member of the sudo group and having the line
%sudo ALL=NOPASSWD: ALL
in your /etc/sudoers file. Of course not asking the password lowers the security of your system.
To answer your question about Qt, remember that bash(1), like all Posix shells, hence /bin/sh, accept the -c argument with a string (actually system(3) is forking a /bin/sh -c). So just execute
process.startDetached("/bin/sh", QStringList()<< "-c"
<< "echo myPass | sudo -S shutdown -r now");
As AntiClimacus answered, puting your root password inside an executable is a bad idea.
You must put your command in a shell script and execute sh or bash with QProcess with your shell script as argument, because your command contains |, which must be interpreted by sh or bash.
However, it's just my opinion, but: I don't think it is a good solution to do what you are doing, i.e. include your root password in an executable.