Two days ago I had an interview in a Buenos Aires’ software company. They decided to test my Linux skills with a simple task, to create a .deb package with certain characteristics.
- They provided to me a binary in Python (which you can download here) that runs in a loop generating a file «log.txt». The idea were to automate all the next tasks within the .deb package or «with the installation of it»:
- Run the binary as a service
- Run the binary as the user «app»
- The binary must be installed in /usr/local/bin/app
- Create a crontab task to sent by email the «log.txt» to test@test.com everyday at midday.
- Rotate the «log.txt» to 5 files and delete the older ones.
All those tasks separately are common to me, but it was my first time dealing with an «.deb» package.
My first attempt to do it failed, I had tried to follow the Debian Packaging Introduction from the official Debian’s website and I tried to «fit that documentation to my needs». I had to deal with a lot of cryptic errors and the process was «too delicate» so after an hour fixing errors in that approach I searched for another way to accomplish the task.
As soon as I started searching I found and amazing and simple way to do it in this thread just a few steps and «tadaaaa» I had my first deb package just using this:
dpkg-deb --build app-1.0
You’ll need to read the whole guide (1 page) to understand all the details.
So, I learnt how to create the deb package. Now it was time to fulfill with the rest of the requirements so I created the folder structure with the required files:
├── app-1.0 # the directory of the project │ │ │ └── usr │ | │ | | └── local | | └── bin | | └── app #the binary provided to me │ └── etc │ └── logrotate.d │ | └── app-logrotate # a file with the instructions to rotate the logs │ | │ └── cront.d │ └── app-mailcron # a file with the instructions to send the mail every day at midday │ └── DEBIAN ├── control # Mandatory file required to build the .deb package ├── postinst # Alternative file required to define the pre-requisites of your installation └── preinst # Alternative file required to define the post-requisites of your installation
Example of control file
Package: app-1.0 Version: 1.0 Section: base Priority: optional Architecture: i386 Depends: libsomethingorrather (>= 1.2.13), anotherDependency (>= 1.2.6) Maintainer: Your Name <you@email.com> Description: Hello World When you need some sunshine, just run this small program! (the space before each line in the description is important)
app-mailcron (Cron Task)
30 12 * * * root /usr/bin/mail -s "today app's log" test@test.com < /home/app/log.txt
app-logrotate (Rotate log.txt)
/home/app/log.txt { rotate 5 weekly }
But that was just the first part of it, now I had to add all the extra requirements. I really don’t know how I found this StackOverflow post but it exlpained the structure of the DEBIAN folder, it caught my attention immediatly when I saw «preinst and postinst» in the structure and the «mkdir» faulty command.
Those names so obvious had to be the files I needed, so I added the next instructions into them to fulfill the requirements:
preinst
#preinst file ################################# create the app user adduser --disabled-password --gecos "" app
postinst
################################## change the owner of the binary chown app:app /usr/local/bin/app ################################## running the app as a process # runuser is not available for deb 7< and other older distros (my first bug occurred here) # runuser -l app -c "setsid /usr/local/bin/app" # use sudo instead sudo -u app -i bash -c 'setsid /usr/local/bin/app 1&2> /tmp/log.txt' #say thanks echo 'Thanks for installing app 1.0 in your PC'
And here’s the result of the whole process, you can use tar to extract its content and check it or install it (dpkg -i app-1.0.deb), but then you will have to deal deleting the «app» user because it doesn’t happen after a deinstall.
It may not be the best result because a matter of time, but at least it fulfill all the requirements.