SRV are ‘service’ type records added in dns zone files. These are added to indicate a certain kind of service runs on a specific port, on a specific domain/subdomain. Many control panel, will give clear distinction to make you select the following items in a srv record:
Protocol Type (TCP/UDP)
Weight
Port
Target Host
Now, if by any chance, you are doing it in a panel like Cyberpanel, or some other zone files, it is highly likely you will have a way to distinct any of these. This simple How to, is for them specially.
If for example, your domain is ‘nanotools.com’, and you are trying to add something like autodiscover.nanotools.com with the following details:
Let’s start with is going to be your ‘name’ field. Usually you would use ‘autodiscover’ as the name field, but in this case, you would have to use it with the protocol with a underscore and a dot (._) in front as following:
autodiscover._tcp
Next, you enter TTL, Prioriy as you would also do. But at the end, you have 3 more fields to enter, but you have one content/value section in your zone. For the SRV records, we fill it like the following:
weight port target_host
It means, we first give the weight, then a space, then the port, then a space, then the target hostname and then a dot to end the section. In our case, it would be:
0 443 fortinet.yourmails.com.
So the whole record going to be as following: (expects priority is 10)
autodiscover._tcp 3600 IN SRV 10 0 443 frotinet.yourmails.com.
If you love to debug and test things in an app shell like me, then you are also a big fan of Tinker in laravel. Tinker is the shell prompt for Laravel and can be used to test and run different commands in php inside the app. You may run the following to hop into the tinker shell in a laravel environment:
php artisan tinker
Once you hop in the tinker, you can call any model or run any php command from the shell.
HOW TO RUN CONTROLLER METHOD FROM TINKER
There are times, you might feel more interest into evaluating a large controller method. To run a controller method, we first need to enter the service container of laravel. Laravel providers a helper method called ‘app()’ to enter the service container. It can then use a method called ‘call’ to access and execute a method inside a controller namespace, like the following:
Repace your controller name and the method name after @. One thing, you need to realize is that the method ‘call’ takes the method reference, not the function itself. That means, you can not add brackets () at the end of method name while giving it in the call method.
HOW TO PASS PARAMETERS TO CONTROLLER FROM TINKER
As discussed earlier, you are passing reference only, not the function, hence you can not pass parameters like we usually do in methods/functions. We need to pass this as an argument in array.
Here is a more constructive way to do this:
# let's make an instance of controller first, can be done using make method of service container
$controller = app()->make('App\Http\Controllers\AdminControllers');
# now let's call the method, inside the container, method name is 'getNewsByCatId'
app()->call([$controller, 'getNewsByCatId']);
# pass a parameter called id = 5
app()->call([$controller, 'getNewsByCatId'], ['id' => 5]);
For example, you have a string like the following:
[lagril] L.A. Girl Pro. Setting HD Matte Finish Spray
While you are scanning the line, you would like to extract the following word from it ‘lagril’, which you are interested in. How to do that?
GETTING TEXT WITHIN BRACKETS USING REGEX IN PYTHON
Our problem falls into a common string extraction problem we face in software engineering. We usually do this using Regular Expressions. Let’s build the regular expression logic first, using regex101.com
We need to find a string that starts with ‘[‘ bracket and ends with ‘]’ bracket, and in the middle, we expect alphanumeric word with small or capital letters, and they can be anything from 0 to any. So, this should be as simple as the following:
\[[A-Za-z0-9]*\]
Now, this should help us target the words that comes within bracket in a sentence/large string. But the trick to grab the text within the bracket is to group them. To use group in regex, we use () brackets without back slash in front. So if the regex is as following:
\[([A-Za-z0-9]*)\]
This will put the matching string in group 1. Now, how can you get what is in the group 1 of a regular expression engine? Let’s dive into python now:
# let's import regular expression engine first
import re
# our string
txt = '[lagril] L.A. Girl Pro. Setting HD Matte Finish Spray'
# our regex search would be as following:
x = re.search(r"\[([A-Za-z0-9]*)\]", txt)
# we know this will put the inner text in group 1. regex object that returned by re.search, has a method called 'group()' to catch the groups matches regex. You may use the following
x.group(1) # prints lagril
Zimbra universal UI is a theme by Zimbra, that is much more modern, professional looking theme, looks much near to Outlook theme. According to Zimbra, this is still in Beta since 2017, and not available anywhere unfortunately to install/download it from Zimbra until you are using one of the Zimbra Cloud by Zimbra Inc.
HOW DID WE MANAGE TO GET ZIMBRA UNIVERSAL UI?
Zeta Alliance had released an unofficial Zimbra 8.8.5 with the Zimbra Universal UI theme in it, that is downloadable here:
tar -xvzf zimbra-ui.tgz
rsync -vrplogDtH zimbra/ /opt/zimbra/jetty/webapps/zimbra/
(Optional) This will install a new theme called ‘clarity’ which is our Zimbra Universal UI theme. You may either use this, and advise your users to choose this as a theme, or replace the default Harmony with this one. To do this, you may do the following:
cd /opt/zimbra/jetty/webapps/zimbra/skins
mv harmony harmony_old
ln -sf clarity harmony
This is done only by creating a softlink for old harmony to clarity theme
Now fix the permissions and restart zimbra to make everything work:
# Fix permission
/opt/zimbra/libexec/zmfixperms -v
service zimbra restart
You may now access Zimbra from your browser to see the new theme loading. If you are having trouble with the http access for your webmail, you may use the following to redirect your http webmail to https webmails
Sometimes, if you restart Zimbra, you see zmconfigd is not starting or saying it’s failed. You may also see the zmconfigd service is not running in the Zimbra admin panel. There are couple of common reasons why zmconfigd fails to start.
Disable IPv6
One reason of zmconfigd fails to start is IPv6, for some reason, it fails to route the IPv6 and fails to start. A quick solution to this problem is to disable ipv6 and restart zmconfigd. You may do this like the following:
#Edit your sysctl.conf file
nano /etc/sysctl.conf
# paste the following inside the file
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
# Save the file, and update sysctl in realtime
sysctl -p
# now try to restart zmconfigd
su - zimbra
zmconfigdctl restart
Now you can check the zmconfigd status with the following, to know if it’s running or not:
If it returns an ID, it means the zmconfigd is running.
Netcat is not installed
Another reason of the error could be because nc is not installed in your system. Zimbra zmconfigd has a dependency on netcat package. Netcat is available through nmap-ncat in centos systems. You may run the following to install netcat:
By default Zimbra will use HTTPs support only and disable HTTP use on the webmail client. But users will always use non http port to access the webclient. Users do not like to type https before the domain each time to get into the webmail client. Zimbra uses Nginx to run the proxy services to access the Javamail Client of Zimbra. Zimbra supports 5 types of proxy services through Nginx:
Even though, if you have defined your routes properly, you are seeing an error of the following:
{
"id": null,
"jsonrpc": "2.0",
"error": {
"http_status": 404,
"code": 404,
"data": {
"name": "werkzeug.exceptions.NotFound",
"debug": "Traceback (most recent call last):\n File \"/opt/odoo/odoo12/odoo/http.py\", line 656, in _handle_exception\n return super(JsonRequest, self)._handle_exception(exception)\n File \"/opt/odoo/odoo12/odoo/http.py\", line 314, in _handle_exception\n raise pycompat.reraise(type(exception), exception, sys.exc_info()[2])\n File \"/opt/odoo/odoo12/odoo/tools/pycompat.py\", line 87, in reraise\n raise value\n File \"/opt/odoo/odoo12/odoo/http.py\", line 1460, in _dispatch_nodb\n func, arguments = self.nodb_routing_map.bind_to_environ(request.httprequest.environ).match()\n File \"/opt/odoo/odoo12-venv/lib64/python3.5/site-packages/werkzeug/routing.py\", line 1563, in match\n raise NotFound()\nwerkzeug.exceptions.NotFound: 404: Not Found\n",
"message": "404: Not Found",
"exception_type": "internal_error",
"arguments": []
},
"message": "404: Not Found"
}
}
This error doesn’t return when you use the http.route as type ‘http’ or default, which is still http, but returns when you use the type ‘json’. One of the cause why the error return is that, you have multiple Odoo databases and Odoo is failing to detect the usable database for the type json. For the type, http, Odoo usually can predict what to use, while for the type json, it can not. For such cases, you would need to use the ‘db-filter’ to add the default database to load for Odoo on the odoo-bin command. If you are using the systemd service file, append the line with the following:
--db-filter=^my_prod$
where ‘my_prod’ is your database name.
So the service ExecStart would look like the following:
I had an interesting challenge today about filtering a list using grep with a set like the following:
senegalese footballer|সেনেগালীয় ফুটবলার
species of insect|কীটপতঙ্গের প্রজাতি
indian cricket player|ভারতীয় ক্রিকেটার
Ajit Manohar Pai|অজিত পৈ|অজিত মনোহর পাই|অজিত ভরদ্বাজ পাই
ajit pai|অজিত পাই
You would need to grep to match them based on pipe. My target was to match lines that had multiple pipes, at least 2. I took a bit greedy approach for this to understand and find how to match Bengali characters using Grep. So, I started matching Alphanumeric first with a Pipe and then Bengali Characters with a Pipe, instead of just counting how many pipes I have at least.
If you are aware, conventional regex can detect and match unicode character sets like, if you want to match a ‘Greek’ set, you can do \p{Greek} in regular expressions. But for some reason, this wasn’t matching the Bengali in the following grep:
grep -Ei "\p{Bengali}" test.txt
I then looked at the grep manual and found a key information. Grep by default uses POSIX regex, and -E is just the extended version of POSIX grep. Unfortunately, this regex engine does not support PCRE, which is basically used to grep the unicode sets here. POSIX can only work with the HEX boundaries, which may sometimes get pretty difficult to match range boundaries of non ascii characters. To make it simpler, you can use PERL Regex that is a PCRE supporting engine. To use that, you may do the following:
grep -Pi "\p{Bengali}" test.txt
To get all the unicode that are available with a set in a PCRE supported Regex engine, you may check the following:
Now, let’s come to the original matching, what we have to match at least 2 pipes, the first one being the basic alphanumeric with whitespace being the simpler one:
grep -Pi "^[A-Za-z0-9\s]+\|" test.txt
Then, we need to add the First Bengali part with whitespace and a pipe
There are times, you may see the following error in your MySQL/MariaDB based Cpanel server:
[ERROR] Can't open and lock privilege tables: Table 'mysql.servers' doesn't exist in engine
The issue is most likely related to your Innodb tablespace got corrupted, and hence some tables under the mysql database got locked out as some of them use Innodb storage engine. One of the outcome of the symptom is, if you try to add a user to a database, it doesn’t add or show the green notification any longer in cpanel mysql databases section. Instead it just stops.
The only and best way to properly fix this would be restore the ‘mysql’ database or just the ‘servers’ table from your backup. If you don’t have one, you may just create the ‘servers’ table using the following SQL statement:
CREATE TABLE `servers` (
`Server_name` char(64) NOT NULL,
`Host` char(64) NOT NULL,
`Db` char(64) NOT NULL,
`Username` char(64) NOT NULL,
`Password` char(64) NOT NULL,
`Port` int(4) DEFAULT NULL,
`Socket` char(64) DEFAULT NULL,
`Wrapper` char(64) NOT NULL,
`Owner` char(64) NOT NULL,
PRIMARY KEY (`Server_name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
You may require to drop the table first. Now, if you can’t do this either, then there is only one way left, is to uninstall your MariaDB installation, and let Cpanel/WHM to install them for you.
Now, you may install the latest MariaDB from WHM >> MariaDB/MySQL Upgrade and proceed accordingly. This should install the latest for you with a fresh ‘mysql’ database for you. But it will not alter your other data files, means your other databases should be fine.
One thing, you need to remember, after a fresh mysql installation with the old data files, you will have the authorizations missing. You would have to recreate the database users manually to get the privileged table filled up.
If you are here, that means, you probably have panicked the same way, I did around 12 years back. I lost my ib_logfile0/ib_logfile1/ibdata1 all at once for a server that excessively utilizes Innodb tables. I had to recover vital data from the same situation today on a random request who does not have backups, and thought it is better to keep this as a document for future.
One key purpose of utilizing Innodb tables instead of MyISAM is that, the benefit on writes. It always outperform MyISAM in writes due to the use of extra efficient buffers. But, this also causes Innodb to vulnerable from crashing. As Innodb stores some sensitive data to 3 specific files, loosing them, also looses some serious mapping instruments for the database engines to recognizes Innodb table structure and data.
Who can follow this technique?
If you have lost any of ib_logfile0, ib_logfile1, ibdata1 or all of them, but still manages to keep the database folder intact with the .frm and .ibd files (which you would, if you have accidentally deleted the log file or the data only) and also have the following option NOT DISABLED in your mysql configuration ‘innodb_file_per_table’. This option is enabled by default, until you are explicitly disabling this to increase performance. A suggestion: only do this, if you keeping real time backups of your databases. Otherwise, it is better to have this enabled
What is ‘innodb_file_per_table’?
Primarily the tablespace stores and uses data from system tablespace for Innodb. But, as this creates a single point of failure from ibdata and log files, Innodb by defaults also stores the tablespace in table’s own data file, which is .ibd file. That means, if I lose the ibdata/logfile mappings, I can still use the .ibd file to restore my tablespace and do the schema to data mapping only if I allowed innodb to store these information to the database’s own .ibd file. You may read more about the parameters from MySQL documentation:
How to Recover an Innodb Table from database files only?
There are two steps to this process. One is to identify and recognize the database schema from the frm file and then basically find a way to import the tablespace from .ibd file and introduce it to innodb engine system tablespace.
First Step First: How to get the schema from .frm files?
First, you must install mysql-utilities tools to get access mysqlfrm tool, you may get the instructions to install this here:
Once this is done, now you have two options to read mysqlfrm files. My favorite way is to use the ‘diagnostic’ attribute. To achieve this, run the following:
I assumed, your database name is ‘your_database’ and the table you are trying to recover is ‘assets’. The above command will return you the schema of ‘CREATE TABLE’ you need to use. First, create a new database, and run this on the SQL console to generate the table first on the new database.
Second Step: Get your data and mapping back from .ibd to system tablespace
Once the database has the table, it will also create a .frm and .ibd file for you. What we need to do, is to first, make it forget the existing .ibd file it created, sync the .ibd file from our collapsed database, make the mysql innodb engine to recognize tablespace from the backup tablespace of this .ibd file and store & use it from system tablespace. These lines are complex, and might sound a bit difficult. No worry, let’s do it.
Run the following command first to let it forget the .ibd it has created now:
alter table assets discard tablespace;
Remember the following, our table name is ‘assets’. If you have a different table name, make sure to replace this accordingly. What this has done, is removed the assets.ibd file it created in /var/lib/mysql/new_database/ folder as we asked him to forget the existing .ibd file. Now we first need to copy the backup/old .ibd file to this location with the correct permission. I would use rsync to make sure permissions remains intact here:
Once this is done, we know, .ibd contains a backup of our original tablespace. We only need to make mysql & innodb recognize this. To achieve this, you may do the following from the Sql console:
alter table assets import tablespace;
If it throws a warning on not being able to file the .cfg file, you may forget it, because it is not essential to have a .cfg to recognize permissions/configurations.
If everything runs well, you should see your rows are back. It’s because innodb has now fetched your tablespace data from .ibd file to system tablespace and it can now recognizes the mapping to your data, viola! All you now need is to repeat the process for all of your innodb tables, and recover the whole database.