📜 ⬆️ ⬇️

My experience setting up an environment for web development

This is not about setting up Denver and not about how to put the LAMP stack. I decided to talk about how we in our team use the environment for development. We develop Web services and ERP systems, but all of this is essentially nothing more than websites. Just complicated inside and sometimes not so beautiful outside.

Just want to say that I do not pretend to describe the ideal environment for Web development. I am pleased to hear criticism, I invite everyone to share their approaches in the comments. In general, let's go.


Wait, what's wrong with Denver?


The main disadvantage of Denver is that projects in production do not work on Denver. So, we cannot guarantee that the scripts carefully debugged on the developer’s computer will not start to “chud” when they get into production. In production, projects usually work on Linux (in our case, this is CentOS or Amazon Linux). In addition, while working on Denver, we will not be able to use the various utilities and tools that we need in the project (for example, catdoc, sphinx search, and more).
')

Ok, but not everyone is ready to work in Linux!


Developing directly in Linux is great, of course, but the truth of life is that most developers use Windows as their main OS on a computer. Therefore, further I will describe our recipe, how to work in Windows, develop websites in Linux.

We use CentOS 7, but I think, without significant changes, everything will work on other distributions.

Create a virtual machine image


OK. The first thing you need to do is put a hypervisor on your computer (VmWare Workstation, Oracle VirtualBox, or maybe some other taste). We use VmWare. After that, we create a virtual machine and deploy the Linux image in it, on which our projects in production will work. We install a Web-server, DBMS, in general, everything that we need to run the project. By the way, if there is a virtual image for production, then even better - you can take it as a basis.

Virtual is most convenient to connect through a bridged-network interface. So it will be a full member of the network and it will be easy to show the results to colleagues or customers, if you forward the port from the outside world.

Network folder


The first question that we had at this stage. We now what, project scripts through putty to edit? And the obvious solution we found was surprisingly simple. In a Windows machine, you need to create a separate folder in which all our projects will be located. You need to share this folder for network access and mount it to the root directory that the web server works with.

To make it all work more reliably, I wrote the cifs_mount.sh script , literally from 2 lines of code, which I put in the virtual machine to run every 5 minutes.
#!/bin/sh if ! mount -t cifs | grep -q `cat /root/file_server` then mount -t cifs -o uid=apache,gid=apache,iocharset=utf8,noserverino,credentials=/root/.cifscreds `cat /root/file_server` /var/www fi 

The script checks if the ball has fallen off (excuse my french). And if it fell off, it mounts it back.

File / root / file_server
//192.168.0.2/Projects

File /root/.cifscreds
username=developvm
password=secretpass


In general, this solution works reliably, like an iron.

But nevertheless there is one small nuance.
Sometimes it happens that when copying large files, a cifs error crashes. As a rule, this is due to the fact that in Windows there is not enough allocated memory for the balls. Departures occur due to the fact that Win7 is configured by default to save memory for network connections, in particular, the size of the allocated memory pool is limited, and if more file processing is required, Win7 sends a fatal interface error to Linux and CIFS crashes.

There are also occasional problems with incomplete loading of pages (no CSS is loaded or errors in general when Apache tries to read the file). And this occurs from time to time without any system.
At the same time in the Apache error log the following errors:
[Tue Oct 20 10:44:28.417589 2015] [core:crit] [pid 9632] (5)Input/output error: [client 192.168.1.5:60666] AH00529: /var/www/project/.htaccess pcfg_openfile: unable to check htaccess file, ensure it is readable and that '/var/www/project/' is executable, referer: http://192.168.1.102/script.php
[Tue Oct 20 10:44:28.418762 2015] [core:error] [pid 9555] (5)Input/output error: [client 192.168.1.5:60670] AH00132: file permissions deny server access: /var/www/project/css/main/layout-main.css, referer: http://192.168.1.102/script.php


To eliminate all these problems at once, you need to edit the Win7 registry, namely:
1. In HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ Session Manager \ Memory Management \ LargeSystemCache, set the value to 1
2. At HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ lanmanserver \ parameters \ size, set the value to 3

After that, restart LanmanServer. “Net stop srv” / “net start srv”. On virtualku remount the ball.


And one more thing concerns the option noserverino
At one time, he spawned this question on stackoverflow. In short, this option is needed. More information can be found on the link.


Do not be afraid of these nuances! They have accumulated with us for almost 10 years of development using this approach.

So what we have. Now we can work with scripts in our familiar code editor in Windows. And to look at results in the browser, coming on our virtual machine. Go ahead.

Subfolders for projects.


And what if we have more than 1 project. Every time to raise a new virtual?! We come to the aid of virtual hosts. You will have to write again a small script flush_vhosts.sh (especially for convenience).
 #!/bin/sh rm /etc/httpd/conf.d/vhosts/* rm /etc/hosts echo '127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4' >> /etc/hosts echo '::1 localhost localhost.localdomain localhost6 localhost6.localdomain6' >> /etc/hosts for D in `find /var/www -maxdepth 1 -mindepth 1 -type d -printf '%f\n'` do echo '<VirtualHost *:80>' >> /etc/httpd/conf.d/vhosts/$D.conf echo "ServerName $D.wde" >> /etc/httpd/conf.d/vhosts/$D.conf echo "ServerAlias *.$D.wde" >> /etc/httpd/conf.d/vhosts/$D.conf echo "DocumentRoot /var/www/$D" >> /etc/httpd/conf.d/vhosts/$D.conf if [[ $D == *"bitrix"* ]] then echo 'php_admin_value mbstring.func_overload 2' >> /etc/httpd/conf.d/vhosts/$D.conf echo 'php_admin_value mbstring.internal_encoding UTF-8' >> /etc/httpd/conf.d/vhosts/$D.conf echo 'php_admin_value max_input_vars 10001' >> /etc/httpd/conf.d/vhosts/$D.conf echo 'php_admin_value pcre.recursion_limit 1000' >> /etc/httpd/conf.d/vhosts/$D.conf fi echo "</VirtualHost>" >> /etc/httpd/conf.d/vhosts/$D.conf echo "127.0.0.1 $D.wde" >> /etc/hosts done systemctl restart httpd.service 

Here is what he does:
1. Clears the configuration of virtual hosts.
2. Clears / etc / hosts.
3. Then it goes through all the subdirectories of our mounted folder and creates a new Apache virtual host for each directory. If the directory name contains the bitrix dreadful word, then it adds a few specific settings for this wonderful CMS to the virtual host config. Adds new entries for created virtual hosts to / etc / hosts.
4. Restarts Apache.

We use project addresses to develop a conditional first-level domain wde (web developer environment). You can use local or someone like that. Our projects under development are available at project1.wde, project2.wde, and so on. In this case, virtual hosts are created with the ServerAlias ​​directive * .your-folder-name.wde, that is, all subdomains will also be processed by the virtual host created for the folder.

Thus, if we need to start working on a new project, it is enough to create a new folder in the common project folder. Run the flush_vhosts.sh script. And in Windows, enter the address for the new project in the file C: \ Windows \ System32 \ drivers \ etc \ host.
192.168.1.166 wde
192.168.1.166 site1.wde
192.168.1.166 site2.wde
... ..

Asterisks, unfortunately, does not support the hosts file. It is necessary to register every address with which we will work. Instead of 192.168.1.166, you need to specify the ip that you assigned to the virtual machine. After that, the corresponding project will open in the browser at site1.wde or site2.wde, and so on.

For convenience, if you use phpMyAdmin, you can configure it with a default host. Then, when accessing any address, when Apache does not find the corresponding project folder, it will open phpMyAdmin. The main thing is not to forget to register this address (for example, just wde) in the hosts file in Windows.

Organization of the boot menu

To make it very convenient. And it was not necessary for new team members to explain how to update the configuration of virtual hosts, set up a network folder, etc. I have written a few more scripts to display and launch frequent actions through the menu. There is nothing supernatural in them, I attach it - maybe someone will also come in handy.

Actually a script that displays the menu. It must be registered in the .bash_profile file of the user's home directory, under which we enter the virtual machine. For the development virtual machine, I think you can be logged in as root, so we add the line ./menu.sh to the /root/.bash_profile file. Now immediately after logging in, our menu will be launched. If necessary, you can exit it all by pressing Ctrl + C.

menu.sh
 #!/bin/sh SCRIPT_DIR=`dirname $0` source $SCRIPT_DIR/utils.sh #menu actions act_net () { nmtui ; } act_folder () { $SCRIPT_DIR/mount_cfg.sh ; } act_flushvhosts () { $SCRIPT_DIR/flush_vhosts.sh ; } act_reboot () { read -p "System is going to reboot, are u sure? (y/N) " key ; if [ $key = "y" ]; then systemctl reboot ; exit fi key= } act_shutdown () { read -p "System is going down, are u sure? (y/N) " key ; if [ $key = "y" ]; then systemctl halt ; exit fi key= } themenu () { clear server_uptime mnt_detect echo "====================================================================" echo "======================= WELCOME to CENTOS WDE!!! ===================" echo "====================================================================" echo "======================== wish you happy coding =====================" echo "====================================================================" echo -e "System time: "$curtime"\tUptime:"$uptime; echo ; echo -e "Mounted folder: "$MNT; echo ; echo "=========================== network info ===========================" echo "`ifconfig -a`" echo ; echo `grep nameserver /etc/resolv.conf` echo ; echo "`route -n`" echo ; echo "====================== current vhosts configs ======================" echo "`ls -1 /etc/httpd/conf.d/vhosts/`" echo ; echo "====================================================================" echo "========================= Available actions: =======================" echo -e "\t\tConfigure ${FG_UN}net${NORM}" echo -e "\t\tConfigure mounted ${FG_UN}folder${NORM}"; echo -e "\t\t${FG_UN}Flush${NORM} virtual hosts"; echo -e "\t\t${FG_UN}Reboot${NORM}"; echo -e "\t\t${FG_UN}Shutdown${NORM}"; echo echo "Type underlined chars(lowercase) and press ENTER or just ENTER to refresh"; echo "Type Ctrl+C to exit to shell"; echo "===================================================================="; } while true do themenu read answer case $answer in "net") act_net;; "folder") act_folder;; "flush") act_flushvhosts;; "reboot") act_reboot;; "shutdown") act_shutdown;; *) echo 'No action found! Refreshing...'; sleep 1; continue;; esac done 


utils.sh - contains functions and variables used in other scripts
 #!/bin/sh set -o pipefail mnt_dir="/var/www" if [ "$interactive" != 'no' ]; then #cursor movements CU_RIGHT=$(tput hpa $(tput cols))$(tput cub 7) #background colors BG_BLACK=$(tput setab 1) BG_RED=$(tput setab 1) BG_GREEN=$(tput setab 2) BG_YELLOW=$(tput setab 3) BG_BLUE=$(tput setab 4) BG_PURPLE=$(tput setab 5) BG_CYAN=$(tput setab 6) BG_WHITE=$(tput setab 7) #foreground colors FG_RED=$(tput setaf 1) FG_GREEN=$(tput setaf 2) FG_YELLOW=$(tput setaf 3) FG_BLUE=$(tput setaf 4) FG_PURPLE=$(tput setaf 5) FG_CYAN=$(tput setaf 6) FG_WHITE=$(tput setaf 7) #text-decoration FG_BOLD=$(tput bold) FG_HB=$(tput dim) FG_UN=$(tput smul) FG_REVERSE=$(tput rev) #back to defaults NORM=$(tput sgr0) fi #functions to display progress dots () { if [ "$interactive" != 'no' ]; then while true; do echo -n "."; sleep 0.5 done fi } estart(){ if [ "$interactive" != 'no' ]; then echo -n "$1" dots & dots_pid=$! fi } efinish(){ estatus=$? if [ "$interactive" != 'no' ]; then if [ "$estatus" -eq 0 ];then echo "[ ${FG_GREEN}OK${NORM} ]" else echo "[ ${FG_RED}FAIL${NORM} ]" fi kill $dots_pid wait $dots_pid 2>/dev/null fi } #detect server uptime server_uptime () { uptime=$(</proc/uptime) uptime=${uptime%%.*} s=$(( uptime%60 )) m=$(( uptime/60%60 )) h=$(( uptime/60/60%24 )) d=$(( uptime/60/60/24 )) uptime=$d'd '$h'h '$m'm '$s's ' curtime=$(date +'%Y-%m-%d %H:%M:%S') } #detect cifs mount mnt_detect () { MNT=$(mount -l | grep $mnt_dir) if [ ! -z "$MNT" ]; then MNT=$FG_GREEN$MNT$NORM else MNT=$FG_RED"error(not found)"$NORM fi } 


mount_cfg.sh - configure network folder settings
 #!/bin/sh SCRIPT_DIR=`dirname $0` source $SCRIPT_DIR/utils.sh clear echo "=========================================" echo " Mounted folder configuration" echo " (/var/www)" echo "=========================================" echo old_address=$(cat /root/file_server) old_username=$(grep 'username=' /root/.cifscreds | awk -F '=' '{ print $2 }') old_password=$(grep 'password=' /root/.cifscreds | awk -F '=' '{ print $2 }') echo "Type new value and press ENTER or just press ENTER to leave current value."; echo ; read -p "Address of fileserver, type like //ip/folder (current value $FG_YELLOW$old_address$NORM): " address ; read -p "Username (current value $FG_YELLOW$old_username$NORM): " username ; read -p "Password (current value $FG_YELLOW$old_password$NORM): " password ; if [ -z "$address" ]; then address=$old_address; fi if [ -z "$username" ]; then username=$old_username; fi if [ -z "$password" ]; then password=$old_password; fi echo "=======================================" echo " New parameters" echo "=======================================" echo -e "IP address of fileserver: "$address echo -e "Username: "$username echo -e "Password: "$password echo "=======================================" echo read -p "Save changes? (y/N) " key ; if [ $key == "Y" -o $key == "y" ]; then echo "username=$username password=$password" > /root/.cifscreds echo "$address" > /root/file_server estart "Unmounting..." umount /var/www efinish estart "Mounting..." /root/cifs_mount.sh efinish echo ; read -p "Done. Press any key" key ; else echo ; read -p "Nothing was changed. Press any key" key ; fi 



Version Control System


It remains to configure your favorite version control system. You can use the desktop-application for Windows, you can work through the command line in putty right in our virtual machine. To whom it is more convenient.

Ps. By the way, one of the greatest discoveries for me was that you can put git or svn directly on the production server. When I once understood it, this feeling was comparable, probably, with the feeling that Archimedes experienced when he sat in the bathroom. After all, you no longer have to suffer with the synchronization of files by ftp \ sftp, just enter svn up or git pull origin master!

Source: https://habr.com/ru/post/282884/


All Articles