I became aware of what an alternative configuration would do after reading an article titled A better way to run PHP-FPM. It was written about a year ago, so it’s kinda disappointing that I came across it while searching for a related topic just last night. If you run your own server and use PHP with PHP-FPM, you need to read that article.
After I read it, I changed the pm options in the pool configuration file to these:
1234 ; Choose how the process manager will control the number of child processes.pm = ondemandpm.max_children = 75pm.process_idle_timeout = 10spm.max_requests = 500The major change was setting pm = ondemand instead of pm = dynamic. And the impact on resource usage was drastic. Here, for example, is the output of
Related Post: Eyes in the Sky: The Rise of Gorgon Stare and How It Will Watch Us Allfree –mt after reloading php5-fpm:
1234 total used free shared buffers cachedMem: 490 196 293 28 9 70–/+ buffers/cache: 116 373Swap: 2047 452 1595Total: 2538 649 1888Compared to the output before, that’s more than a 50% drop in RAM usage. And the reason became obvious when I viewed top again:
1234 2778 mysql 20 1359152 56708 3384 S 0.0 11.3 2:11.06 mysqld26896 root 20 373828 19000 13532 S 0.0 3.8 :02.42 php5–fpm 25818 root 20 64208 4148 1492 S 0.0 0.8 :01.88 php5–fpm25818 root 20 64208 4148 1492 S 0.0 0.8 :01.88 php5–fpm17385 root 20 64208 4068 1416 S 0.0 0.8 :02.23 php5–fpm 1465 ossec 20 15592 2960 480 S 0.0 0.6 :08.60 ossec–analysisd1500 root 20 6312 2072 328 S 0.0 0.4 :45.55 ossec–syscheckd 1 root 20 33444 1940 812 S 0.0 0.4 :03.29 initDid you notice that there are no child processes? What happened to them? That’s what setting pm = ondemand does. A child process is spawned only when needed. After it’s done its job, it remains idle for 10 seconds (pm.process_idle_timeout = 10s) and then dies.
So what I have is a simple modification to the default PHP-FPM settings that saved me more than 50% of RAM. Sure, the server hasn’t come under heavy traffic, but I think it can withstand a reasonably heavy traffic, considering that it only has 512 MB of RAM. And with Nginx microcaching configured, I think it will do very well. There are other aspects of PHP-FPM and Percona MySQL that I’ve not optimized yet, so stay tuned. This was just to pass on a little tip that I found useful.
How To Install the Apache Web Server on Debian 10
Step 5 — Setting Up Virtual Hosts (Recommended)
When using the Apache web server, you can use virtual hosts (similar to server blocks in Nginx) to encapsulate configuration details and host more than one domain from a single server. In the following commands, replace
your_domain
with your own domain name. To learn more about setting up a domain name with DigitalOcean, see our Introduction to DigitalOcean DNS.Apache on Debian 10 has one server block enabled by default that is configured to serve documents from the
/var/www/html
directory. While this works well for a single site, it can become unwieldy if you are hosting multiple sites. Instead of modifying/var/www/html
, let’s create a directory structure within/var/www
for ouryour_domain
site, leaving/var/www/html
in place as the default directory to be served if a client request doesn’t match any other sites.Create the directory for
your_domain
as follows, using the-p
flag to create any necessary parent directories:sudo mkdir -p /var/www/<span class="highlight">your_domain</span>
Next, assign ownership of the directory with the
$USER
environmental variable:
- sudo chown -R $USER:$USER /var/www/your_domain
The permissions of your web roots should be correct if you haven’t modified your
unmask
value, but you can make sure by typing:
- sudo chmod -R 755 /var/www/your_domain
Next, create a sample
index.html
page usingnano
or your favorite editor:
- nano /var/www/your_domain/index.html
Inside, add the following sample HTML:
/var/www/your_domain/index.html<html> <head> <title>Welcome to <span class="highlight">your_domain</span>!</title> </head> <body> <h1>Success! The <span class="highlight">your_domain</span> virtual host is working!</h1> </body> </html>
Save and close the file when you are finished.
In order for Apache to serve this content, it’s necessary to create a virtual host file with the correct directives. Instead of modifying the default configuration file located at
/etc/apache2/sites-available/000-default.conf
directly, let’s make a new one at/etc/apache2/sites-available/<span class="highlight">your_domain</span>.conf
:
- sudo nano /etc/apache2/sites-available/your_domain.conf
Paste in the following configuration block, which is similar to the default, but updated for our new directory and domain name:
/etc/apache2/sites-available/your_domain.conf<VirtualHost *:80> ServerAdmin <span class="highlight">admin@your_email_domain</span> ServerName <span class="highlight">your_domain</span> ServerAlias <span class="highlight">www.your_domain</span> DocumentRoot /var/www/<span class="highlight">your_domain</span> ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
Notice that we’ve updated the
DocumentRoot
to our new directory andServerAdmin
to an email that theyour_domain
site administrator can access. We’ve also added two directives:ServerName
, which establishes the base domain that should match for this virtual host definition, andServerAlias
, which defines further names that should match as if they were the base name.Save and close the file when you are finished.
Let’s enable the file with the
a2ensite
tool:
- sudo a2ensite your_domain.conf
Disable the default site defined in
000-default.conf
:
- sudo a2dissite 000-default.conf
Next, let’s test for configuration errors:
- sudo apache2ctl configtest
You should see the following output:
OutputAH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message Syntax OK
Restart Apache to implement your changes:
- sudo systemctl restart apache2
Initial Server Setup with Debian 10
Additional Instructions: Lets Encrypt, fail2ban
To ensure that the server cannot be attacked through the HTTPOXY vulnerability, we will disable the HTTP_PROXY header in apache globally by adding the configuration file /etc/apache2/conf-available/httpoxy.conf.
Note: The vulnerability is named httpoxy (without ‘r’) and therefore the file where we add the config to prevent it is named httpoxy.conf and not httproxy.conf, so there is no ‘r’ missing in the filename.
nano /etc/apache2/conf-available/httpoxy.conf
Paste the following content to the file:
<IfModule mod_headers.c> RequestHeader unset Proxy early </IfModule>And enable the module by running:
a2enconf httpoxy systemctl restart apache2
11 Install Let’s Encrypt
ISPConfig 3.1 has support for the free SSL Certificate authority Let’s encrypt. The Let’s Encrypt function allows you to create free SSL certificates for your website from within ISPConfig.
Now we will add support for Let’s encrypt.
cd /usr/local/bin wget https://dl.eff.org/certbot-auto chmod a+x certbot-auto ./certbot-auto --install-only
What are the Top 500,000 Websites?
Alexa Internet creates a list of the top 1,000,000 sites on the web. It’s updated daily, and best of all it’s free.
Unicode & Character Encodings in Python: A Painless Guide
Python
import unicodedata
>> print(u”Test\u2014It”)
Test—It
>> s = u”Test\u2014It”
>> ord(s[4])
8212
>>> chr(732)
‘˜’
>>> c = chr(732)
>>> ord(c)
732https://stackoverflow.com/questions/2831212/python-sets-vs-lists
escape_characters = set()
if ord(c) in escape_characters:
>> unicodedata.name(c)
‘SMALL TILDE’JavaScript:
String.fromCharCode(parseInt(unicode,16))
>> c = String.fromCharCode(732);
“˜”>> c.charCodeAt(0);732>> String.fromCharCode(0904)>> c = String.fromCharCode(parseInt(‘2014’,16)) 2014 = hex
“—”>> c.charCodeAt(0);
8212c = String.fromCharCode(39);>> c.charCodeAt(0);
39jsFiddle
var str = String.fromCharCode(e.which);
$(‘#charCodeAt’)[0].value = str.charCodeAt(0);
$(‘#fromCharCode’)[0].value = encodeURIComponent(str);jQuery String Functions
- charAt(n): Returns the character at the specified index in a string. The index starts from 0.
1
var
str =
"JQUERY By Example"
;
2
var
n = str.charAt(2)
3
4
//Output will be "U"
- charCodeAt(n): Returns the Unicode of the character at the specified index in a string. The index starts from 0.
1
var
str =
"HELLO WORLD"
;
2
var
n = str.charCodeAt(0);
3
4
//Output will be "72"
Mathias Bynens: JavaScript Has a Unicode Problem:
As my JavaScript escapes tool would tell you, the reason is the following:
>> <span class="string">'ma\xF1ana'</span> == <span class="string">'man\u0303ana'</span> <span class="literal">false</span> >> <span class="string">'ma\xF1ana'</span>.length <span class="number">6</span> >> <span class="string">'man\u0303ana'</span>.length <span class="number">7</span>
The first string contains U+00F1 LATIN SMALL LETTER N WITH TILDE, while the second string uses two separate code points (U+006E LATIN SMALL LETTER N and U+0303 COMBINING TILDE) to create the same glyph. That explains why they’re not equal, and why they have a different
length
.However, if we want to count the number of symbols in these strings the same way a human being would, we’d expect the answer
6
for both strings, since that’s the number of visually distinguishable glyphs in each string. How can we make this happen?In ECMAScript 6, the solution is fairly simple:
<span class="function"><span class="keyword">function</span> <span class="title">countSymbolsPedantically</span>(<span class="params">string</span>) </span>{ <span class="comment">// Unicode Normalization, NFC form, to account for lookalikes:</span> <span class="keyword">var</span> normalized = string.normalize(<span class="string">'NFC'</span>); <span class="comment">// Account for astral symbols / surrogates, just like we did before:</span> <span class="keyword">return</span> punycode.ucs2.decode(normalized).length; }
The
normalize
method onString.prototype
performs Unicode normalization, which accounts for these differences. If there is a single code point that represents the same glyph as another code point followed by a combining mark, it will normalize it to the single code point form.>> countSymbolsPedantically(<span class="string">'mañana'</span>) <span class="comment">// U+00F1</span> <span class="number">6</span> >> countSymbolsPedantically(<span class="string">'mañana'</span>) <span class="comment">// U+006E + U+0303</span> <span class="number">6</span>
For backwards compatibility with ECMAScript 5 and older environments, a
String.prototype.normalize
polyfill can be used.Turning a code point into a symbol
String.fromCharCode
allows you to create a string based on a Unicode code point. But it only works correctly for code points in the BMP range (i.e. from U+0000 to U+FFFF). If you use it with an astral code point, you’ll get an unexpected result.>> <span class="built_in">String</span>.fromCharCode(<span class="number">0x0041</span>) <span class="comment">// U+0041</span> <span class="string">'A'</span> <span class="comment">// U+0041</span> >> <span class="built_in">String</span>.fromCharCode(<span class="number">0x1F4A9</span>) <span class="comment">// U+1F4A9</span> <span class="string">''</span> <span class="comment">// U+F4A9, not U+1F4A9</span>
The only workaround is to calculate the code points for the surrogate halves yourself, and pass them as separate arguments.
>> <span class="built_in">String</span>.fromCharCode(<span class="number">0xD83D</span>, <span class="number">0xDCA9</span>) <span class="string">'💩'</span> <span class="comment">// U+1F4A9</span>
If you don’t want to go through the trouble of calculating the surrogate halves, you could resort to Punycode.js’s utility methods once again:
>> punycode.ucs2.encode([ <span class="number">0x1F4A9</span> ]) <span class="string">'💩'</span> <span class="comment">// U+1F4A9</span>
Luckily, ECMAScript 6 introduces
String.fromCodePoint(codePoint)
which does handle astral symbols correctly. It can be used for any Unicode code point, i.e. from U+000000 to U+10FFFF.>> <span class="built_in">String</span>.fromCodePoint(<span class="number">0x1F4A9</span>) <span class="string">'💩'</span> <span class="comment">// U+1F4A9</span>
For backwards compatibility with ECMAScript 5 and older environments, use a
String.fromCodePoint()
polyfill.
Getting a code point out of a string
Similarly, if you use
String.prototype.charCodeAt(position)
to retrieve the code point of the first symbol in the string, you’ll get the code point of the first surrogate half instead of the code point of the pile of poo character.>> <span class="string">'💩'</span>.charCodeAt(<span class="number">0</span>) <span class="number">0xD83D</span>
Luckily, ECMAScript 6 introduces
String.prototype.codePointAt(position)
, which is likecharCodeAt
except it deals with full symbols instead of surrogate halves whenever possible.>> <span class="string">'💩'</span>.codePointAt(<span class="number">0</span>) <span class="number">0x1F4A9</span>
For backwards compatibility with ECMAScript 5 and older environments, use a
String.prototype.codePointAt()
polyfill.
Real-world bugs and how to avoid them
This behavior leads to many issues. Twitter, for example, allows 140 characters per tweet, and their back-end doesn’t mind what kind of symbol it is — astral or not. But because the JavaScript counter on their website at some point simply read out the string’s
length
without accounting for surrogate pairs, it wasn’t possible to enter more than 70 astral symbols. (The bug has since been fixed.)Many JavaScript libraries that deal with strings fail to account for astral symbols properly.
Introducing… The Pile of Poo Test™
Whenever you’re working on a piece of JavaScript code that deals with strings or regular expressions in some way, just add a unit test that contains a pile of poo (
💩
) in a string, and see if anything breaks. It’s a quick, fun, and easy way to see if your code supports astral symbols. Once you’ve found a Unicode-related bug in your code, all you need to do is apply the techniques discussed in this post to fix it.
Stack Overflow on String.fromCharCode():
inArray
returns the index of the element in the array, not a boolean indicating if the item exists in the array. If the element was not found,-1
will be returned.So, to check if an item is in the array, use:
<span class="kwd">if</span><span class="pun">(</span><span class="pln">jQuery</span><span class="pun">.</span><span class="pln">inArray</span><span class="pun">(</span><span class="str">"test"</span><span class="pun">,</span><span class="pln"> myarray</span><span class="pun">)</span> <span class="pun">!==</span> <span class="pun">-</span><span class="lit">1</span><span class="pun">)</span>
- String.fromCodePoint() Not supported by Internet Explorer. From Safari 10
- String.fromCharCode() Supported since for ever, double as fast
- The difference:
Although most common Unicode values can be represented with one 16-bit number (as expected early on during JavaScript standardization) and fromCharCode() can be used to return a single character for the most common values (i.e., UCS-2 values which are the subset of UTF-16 with the most common characters), in order to deal with ALL legal Unicode values (up to 21 bits), fromCharCode() alone is inadequate. Since the higher code point characters use two (lower value) “surrogate” numbers to form a single character, String.fromCodePoint() (part of the ES6 draft) can be used to return such a pair and thus adequately represent these higher valued characters.