A bottom-up look or Ubuntu Server for an electronics developer. Part 2
We continue to develop the theme of using a computer with ubuntu server as a device for connecting the world of microcontrollers with the world of personal computers.
Link to Part 1
I recall that the article describes the practice of using the described technique and does not set out to cover all the depths and capabilities of modern equipment. This is one of the options for solving the problem.
In this part, I will show you how to go through the following points:
Friends, I look forward to your interesting comments and valuable advice. If you lied where - do not get very angry, just indicate what can be done better. I hope that part 3 will appear about a large script, auto-installation ... maybe something else.
Link to Part 1
I recall that the article describes the practice of using the described technique and does not set out to cover all the depths and capabilities of modern equipment. This is one of the options for solving the problem.
In this part, I will show you how to go through the following points:
Static IP + DHCP Server
Currently, only two devices are supposed to be in the local network. The server itself and the host machine. Based on this simplicity, we will configure the Ubuntu server.
Static IP
Reference information
1. To find out the logical name of the network interface, do:
The option of using the ifconfig function (as an analog of ipconfig in windows) can sometimes give only loop 127.0.0.1. The name of the interface is hardware dependent. On two different machines, I installed ubuntu from the same flash drive and there were different names of network interfaces. enp3s0 is a classification by bus and device number, as I understand it. There are also from such a series eth0 and such ens35. Do not be alarmed.
2. Modify the network configuration file
It should be like this:
Press cntrl-x - to exit the editor.
Press y - to save the changes
. 3. Restart the network service:
DHCP server
Basic information
1. Editing files for the DHCP server
In file
2. If you use the gethostbyname () function, then in the file
The name of the pc (ubuntu) is stored in the / etc / hostname file. Can look through
3. Reboot the network service:
SSH access
In theory, having connected a stationary computer now, we will get an IP for it and will be able to access it via SSH. For access from Windows, I used the PuTTY utility. There, in the PuTTY program files, there is a utility for transmitting data over the network.
Here is the composition of the batch file for transferring files from Ubuntu to Windows.
And to upload to the server
Static IP
Reference information
1. To find out the logical name of the network interface, do:
sudo lshw -C network
and look for a line logical name: enp3s0
The option of using the ifconfig function (as an analog of ipconfig in windows) can sometimes give only loop 127.0.0.1. The name of the interface is hardware dependent. On two different machines, I installed ubuntu from the same flash drive and there were different names of network interfaces. enp3s0 is a classification by bus and device number, as I understand it. There are also from such a series eth0 and such ens35. Do not be alarmed.
2. Modify the network configuration file
sudo nano /etc/network/interfaces
(nano is this little text editor) It should be like this:
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
source /etc/network/interfaces.d/*
# The loopback network interface
auto lo
iface lo inet loopback
# My local network.
allow-hotplug enp3s0
iface enp3s0 inet static
address 172.16.55.1
netmask 255.255.255.0
gateway 172.16.55.1
Press cntrl-x - to exit the editor.
Press y - to save the changes
. 3. Restart the network service:
service networking restart
DHCP server
Basic information
1. Editing files for the DHCP server
sudo nano /etc/default/isc-dhcp-server
find the line INTERFACES=""
Is the name of the interface for the DHCP server. In our case, it should be like this:INTERFACES="enp3s0"
In file
sudo nano /etc/dhcp/dhcpd.conf
need to addsubnet 172.16.55.0 netmask 255.255.255.0{
range 172.16.55.2 172.16.55.100;
}
Within this subnet, the DHCP server will issue addresses in the range from 2 to 100. 2. If you use the gethostbyname () function, then in the file
sudo nano /etc/hosts
The name of the PC and IP should be written. Perhaps there is a more convenient way to get your own IP, but he did not give in to me.127.0.0.1 localhost
172.16.55.1 ubuntu
The name of the pc (ubuntu) is stored in the / etc / hostname file. Can look through
sudo cat /etc/hostname
and a million more ways. 3. Reboot the network service:
service networking restart
SSH access
In theory, having connected a stationary computer now, we will get an IP for it and will be able to access it via SSH. For access from Windows, I used the PuTTY utility. There, in the PuTTY program files, there is a utility for transmitting data over the network.
Here is the composition of the batch file for transferring files from Ubuntu to Windows.
d:\"Program Files"\PuTTY\pscp.exe ubuntu@172.16.55.1:/home/ubuntu/tool/* "F:/WORK/SERVER/tool/"
And to upload to the server
d:\"Program Files"\PuTTY\pscp.exe "F:/WORK/SERVER/tool/*" ubuntu@172.16.55.1:/home/ubuntu/tool/
We put the driver from FTDI
FTDI drivers come in compressed form. The package contains the drivers themselves, libraries, examples of use and the README.pdf file, which was most interesting. From the D3XX Programmers Guide file, it’s never clear how to use the Linux driver. I even had to write FTDI support to those, since they respond promptly and on business. It would be possible not to write if I immediately opened this archive. But useful were the links they sent, examples of wiring and circuitry.
As shown above, using the pscp utility from the PuTTY kit, we copy the driver to the server. I had d3xx-linux-i686-0.5.0.tar.bz2. We go into this folder on the server and do
Further, according to the FTDI instruction, we execute:
As shown above, using the pscp utility from the PuTTY kit, we copy the driver to the server. I had d3xx-linux-i686-0.5.0.tar.bz2. We go into this folder on the server and do
tar -xvf d3xx-linux-i686-0.5.0.tar.bz2
Further, according to the FTDI instruction, we execute:
cd linux-i686
sudo rm -f /usr/lib/libftd3xx.so
sudo cp -f libftd3xx.so /usr/lib
sudo cp -f libftd3xx.so.0.5.0 /usr/lib
sudo cp -f 51-ftd3xx.rules /etc/udev/rules.d
sudo udevadm control --reload-rules
Compiling the program
I wrote the program in codeBlocks and, with the exception of certain points, including due to FTDI, it is compatible with Windows. It stopped compiling for Windows when I put the h file from the driver for linux D3XX there (there were no problems with the D2XX and FT232RL chip).
Now makefile. Programmers
already know why it is needed, just indicate the features: STATLIB = libftd3xx.a - indicate the name of the library for Linux
CFLAGS = $ (DEPENDENCIES) -Wall -Wextra -std = c ++ 11 - enable c ++ 11
Thus, the main.c ftd3xx.h makefile libftd3xx.a and other project files are in the project folder. And to compile the project now you need to go into this folder and do
Now makefile. Programmers
already know why it is needed, just indicate the features: STATLIB = libftd3xx.a - indicate the name of the library for Linux
CFLAGS = $ (DEPENDENCIES) -Wall -Wextra -std = c ++ 11 - enable c ++ 11
makefile example for one main.cpp project file
CC=g++
UNAME := $(shell uname)
ifeq ($(UNAME), Darwin)
DEPENDENCIES := -lpthread -ldl -lobjc -framework IOKit -framework CoreFoundation
else
DEPENDENCIES := -lpthread -ldl -lrt
endif
CFLAGS=$(DEPENDENCIES) -Wall -Wextra -std=c++11
STATLIB=libftd3xx.a
APP = prgr
all: $(APP)
$(APP): main.o
$(CC) -o $(APP) main.o $(STATLIB) $(CFLAGS)
main.o: main.cpp
$(CC) -c -o main.o main.cpp $(CFLAGS)
clean:
rm -f *.o ; rm $(APP)
Thus, the main.c ftd3xx.h makefile libftd3xx.a and other project files are in the project folder. And to compile the project now you need to go into this folder and do
make
daemon
The role of daemons on Linux is similar to the role of services on Windows. These are programs that live in the background and do all kinds of peripheral work. It all starts with systemd, the program that starts first, has PID = 1, respectively, and starts all other background tasks through scripts. Digging into Ubuntu, I was surprised how much of everything inside is built on scripts. You have already seen how static IP changes, programs are configured, by simple correction of files in a text editor.
By completing
So, when the daemon starts, a script is executed that indicates when and how the program needs to be started, how to stop it or restart it. In order for the daemon to work normally, the program at startup must save to the file, the path to which is specified in the script, its PID and switch to another stream (in the background).
The demon guide led me into sadness and longing. Having greatly simplified the daemon, I turned it into a utility for launching any program. But the mandatory part has not changed. In addition, he logs to check if something happens.
Compile the demon.
At the moment, in our working directory, let's say / home / ubuntu / daemon /, we have:
daemon -
prgr daemon program -
prgr.strt program - script that needs to be executed before the program starts (if necessary)
prgr.stop - script that you need run to stop the program (if necessary)
It is necessary to allow the programs to work:
Now we need a script for systemd.
Do
In the script, briefly:
Description - a short name-description
After - what is required to run
Type = forking - systemd assumes that the service starts once and the process branches with the completion of the parent process.
PIDFile - file with the PID of the program from the
ExecStartPre daemon - before starting the
ExecStart program - program with the
ExecStop parameters - how to stop
WantedBy - the level at which to start
Now you can try to start everything.
We write
If everything is error-free, then run:
After that, see the demon’s log, everything should go.
To make autoload work
By completing
ps -el
You will see a list of running programs with their PID. PID is a mandatory identifier of a running program, according to which the OS monitors this program. In extreme situations, you can bang the program for this PID from the terminal - write kill and PID (it may come in handy for debugging). So, when the daemon starts, a script is executed that indicates when and how the program needs to be started, how to stop it or restart it. In order for the daemon to work normally, the program at startup must save to the file, the path to which is specified in the script, its PID and switch to another stream (in the background).
The demon guide led me into sadness and longing. Having greatly simplified the daemon, I turned it into a utility for launching any program. But the mandatory part has not changed. In addition, he logs to check if something happens.
daemon code
void SetPidFile(char* Filename)
{
FILE* f;
f = fopen(Filename, "w+");
if (f)
{
fprintf(f, "%u", getpid());
fclose(f);
}
}
int main( int argc, char** argv )
{
char toolfile[32];
char folder[32];
intptr_t ret;
FILE* logfile;
if( argc!=3 )
{
printf( "Write address of the program and name: /home/ubuntu/tool/ tool\n");
return -1;
}
pid_t pid, sid;
pid = fork();
if (pid < 0)
{
sleep(1);
return -1;
}
//We got a good pid, Close the Parent Process
if (pid > 0) {
return 0;
}
//Create a new Signature Id for our child
sid = setsid();
if (sid < 0)
{
return -1;
}
//Change File Mask
umask(0);
//Save PID
memcpy( toolfile, argv[0], strlen(argv[0]) );
memcpy( toolfile + strlen(argv[0]), ".log", 4 );
memset( toolfile + strlen(argv[0]) + 4, 0, 1 );
printf( "Daemon:: log to:%s\n", toolfile );
logfile = fopen( toolfile, "w" );
fprintf( logfile, "Daemon:: started with 0=%s 1=%s 2=%s\n", argv[0], argv[1], argv[2] );
memset( toolfile, 0, 32 );
memcpy( toolfile, argv[0], strlen(argv[0]) );
memcpy( toolfile + strlen(argv[0]), ".pid", 4 );
memset( toolfile + strlen(argv[0]) + 4, 0, 1 );
SetPidFile( toolfile );
fprintf( logfile, "Daemon:: PID=%u saved in the %s\n", getpid(), toolfile );
memset( folder, 0, 32 );
memcpy( folder, argv[1], strlen(argv[1]) );
fflush ( logfile );
memset( toolfile, 0, 32 );
memcpy( toolfile, folder, strlen(argv[1]) );
memset( toolfile + strlen(argv[1]), '/', 1 );
memcpy( toolfile + strlen(argv[1]) + 1, argv[2], strlen(argv[2]) );
//Change Directory
//If we cant find the directory we exit with failure.
if ((chdir(folder)) < 0)
{
fprintf( logfile, "Daemon:: Program folder was not found:%s\n", folder );
fclose( logfile );
return -1;
}
//Close Standard File Descriptors
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
fprintf( logfile, "Daemon:: Program started\n" );
fflush ( logfile );
ret = execl( toolfile, folder, NULL );
if( ret==-1 )
{
fprintf( logfile, "Daemon:: execl error: %s. File=%s Folder=%s\n", strerror(errno), toolfile, folder );
fclose( logfile );
return -1;
}
fprintf( logfile, "Daemon:: closed\n" );
fclose( logfile );
return 0;
}
Compile the demon.
At the moment, in our working directory, let's say / home / ubuntu / daemon /, we have:
daemon -
prgr daemon program -
prgr.strt program - script that needs to be executed before the program starts (if necessary)
prgr.stop - script that you need run to stop the program (if necessary)
It is necessary to allow the programs to work:
sudo chmod 755 ./tool
sudo chmod 755 ./daemon
Now we need a script for systemd.
Do
sudo nano /etc/systemd/system/mydaemon.service
and write our script there.mydaemon.service
[Unit]
Description=my service
After=network.target
After=isc-dhcp-server.service
[Service]
Type=forking
PIDFile=/home/ubuntu/daemon/daemon.pid
ExecStartPre=/bin/sh /home/ubuntu/daemon/prgr.strt
ExecStart=/home/ubuntu/daemon/daemon /home/ubuntu/daemon/prgr prgr
ExecStop=/bin/sh /home/ubuntu/daemon/prgr.stop
Restart=always
TimeoutSec=5
[Install]
WantedBy=multi-user.target
In the script, briefly:
Description - a short name-description
After - what is required to run
Type = forking - systemd assumes that the service starts once and the process branches with the completion of the parent process.
PIDFile - file with the PID of the program from the
ExecStartPre daemon - before starting the
ExecStart program - program with the
ExecStop parameters - how to stop
WantedBy - the level at which to start
Now you can try to start everything.
We write
systemctl daemon-reload
systemctl status mydaemon
If everything is error-free, then run:
systemctl start mydaemon
After that, see the demon’s log, everything should go.
To make autoload work
systemctl enable mydaemon
Friends, I look forward to your interesting comments and valuable advice. If you lied where - do not get very angry, just indicate what can be done better. I hope that part 3 will appear about a large script, auto-installation ... maybe something else.