richardforth / apache2buddy Goto Github PK
View Code? Open in Web Editor NEWapache2buddy
License: Apache License 2.0
apache2buddy
License: Apache License 2.0
A task that's not particularly time consuming (but is performed every time) is the location of a vhost, its configuration file, and its relevant details.
e.g.
Displaying those three directives for every vhost will spam up the output if there are too many. Perhaps add logic to only display those things if there are 5 or fewer vhosts.
RHEL 6.8, Apache -2.2.15, PHP 5.3.3
Analyzing apache memory use...
[ INFO ] httpd is currently using 3087.04 MB of memory.
[ CRITICAL ] Error getting a list of PIDs
DEBUG -> Process Name: /usr/sbin/httpd
DEBUG -> Apache_user: http-we+
DEBUG -> Search Type: high
Added on behalf of S.Waller
This one might be interesting, though, for example what would be a source of truth? Would we instead hard code in a bunch of known issues and test against those, and as we find new vulnerabilities, add those too? Though, thinking out loud, nine times out of ten it’s the application that is vulnerable more so than the apache service itself, so perhaps some hardening guidance and checking for package updates might cover this? (Issues #2 and #3).
Not sure if this is possible but wondered if a code review could find a way to run apache2buddy.pl without superuser permissions.
In fact it would be kind of cool if eventually we could hard fail if it is run as root.
The problem may be that certain actions required root privileges.
This issue serves to document all those actions that actually do require root privilege and to investigate if these are possible to run as an ordinary user?
The truth is the fact that it needs superuser access scares me. I'd be much more comfortable if apache2buddy.pl could be run by ordinary users in case of compromised code or bugs that might run amok unchecked.
I'd also be more comfortable knowing if this is not possible to achieve, specifically why that is the case.
For example:
[ INFO ] Your MaxClients setting is 256.
[ INFO ] Current Apache Process Count is 257 (including the parent pid).
or even incorporated in one line:
[ INFO ] Your MaxClients setting is 256. Current Count is 257 (including the parent pid).
be sure to do a grep -v apache2buddy.pl as we found on a previous section of code that grepping for apache2 in the process list will also fish out apache2buddy.pl as well,
something like
ps aux | egrep "httpd|apache2" | grep -v apache2buddy | grep -v grep | wc -l
should do it, but needs some testing.
If people don't like the idea of including the parent I can always minus 1 and report 256 instead (given the above examples). I quite like the idea of leaving the parent process in the count and explaining why we see 257, not 256....... user education.
$UNDERLINE = ""; # SUPPRESS COLORS
$BOLD = ""; # SUPPRESS COLORS
$UNDERLINE = ""; # SUPPRESS COLOR
Added on behalf of S. Waller
Hi,
I'm running cPanel and when is looking for a pid the script stop.
[ INFO ] OS Name: CentOS
[ INFO ] OS Release: 6.8
[ OK ] Apache2buddy supports this OS Release/Version.
[ INFO ] We are checking the service running on port 80...
[ INFO ] The process listening on port 80 is /usr/sbin/httpd
[ INFO ] The process running on port 80 is Apache/2.4.23 (cPanel).
[ INFO ] Apache has been running 70d 13h 16m 31s.
[ INFO ] The full path to the Apache config file is: /etc/apache2/conf/httpd .conf
[ INFO ] Apache is using event model.
[ WARNING ] Non-standard apache set-up, apache is running as UID: 99 (nobody). Expecting UID 48 ('apache' or 'www-data').
[ INFO ] Apache runs as nobody.
[ INFO ] pidfile setting is /etc/apache2/run/httpd.pid.
[ CRITICAL ] Unable to open pid file /var/run/httpd/httpd.pid. Exiting.
Added on behalf of S. Waller
Detecting Large Log Files...
PRO TIP: This is a precursor to the following 2 checks that may appear to hang if there are very large error logs.
PRO TIP: If those process do appear to hang, press CTRL + c to exit the program, and then go check the logs we report below, if any.
[ CRITICAL ] /var/log/httpd/REDACTED-access.log --> 2.25GB[ CRITICAL ] /var/log/httpd/REDACTED-error.log-20170108 --> 9.61GB[ CRITICAL ] /var/log/httpd/REDACTED-error.log --> 11.05GB[ CRITICAL ] /var/log/httpd/REDACTED.log-20170108 --> 2.06GB[ CRITICAL ] Consider setting up a log rotation policy.
[ CRITICAL ] Note: Log rotation should already be set up under normal circumstances, so very
[ CRITICAL ] large error logs can indicate a fundmeneal issue with the website / web application.
As part of the ongoing development of this application I am going to be running some scream tests.
If you happen to see the scream test please take part by adding a reaction to this issue. any reaction will do. But preferably a thumbs down so I can see who is most upset about its non-availability.
Note: during the scream test there is a master_backup branch that you can access but the main domain "apache2buddy.pl" will still go to master (which I will merge with screamtest branch for the actual test).
In the most lay term, it simply means turning an application feature off, and waiting for the screams to start - as in "Arrrrrgghhh NOOOOOOOOOO". The idea behind this test is to determine the level of usage to warrant re-activation and on going development of additional features.
The terminology comes from old days of IT Support where there's a dusty old server in the corner that no one knows the maintainer or if it is still in active use, they would turn it off and wait for the phone calls to come in. Usually the users would be screaming down the phone, hence "Scream Test".
It was a way of determining if a piece of hardware such as a server was still in active use in preparation for either decommissioning or conversely, justification for a hardware refresh.
I plan to be quite specific about the start and end dates of the scream test so this issue will be updated with more information, once everything is confirmed, as will the output in the scream test script when executed.
I have been asking for feedback for a while but have not received any for over a month, and I just need to know if this is something I should be devoting my time to. Don't worry though, there are no plans to decommission apache2buddy. It's quite stable at the moment but I am thinking about feature requests and additional work to make it even better.
Well, this issue #13 is a screamtest in itself, please "react" to this issue with a thumbs down, and tell all your friends to vote too, if I get a high hit count, chances are I will not go ahead with it. If I get like three thumbs down then I must complete scream testing.
The master branch will be restored and functionality will come back, but development and feature requests will take much less priority and issues will take longer to resolve.
[ INFO ] We are checking the service running on port 80...
sh: netstat: command not found
[ WARNING ] Nothing seems to be listening on port 80. Falling back to process list...
sh: netstat: command not found
Use of uninitialized value $real_port in concatenation (.) or string at - line
1429 (#1)
(W uninitialized) An undefined value was used as if it were already
defined. It was interpreted as a "" or a 0, but maybe it was a mistake.
To suppress this warning assign a defined value to your variables.
To help you figure out what was undefined, perl will try to tell you
the name of the variable (if any) that was undefined. In some cases
it cannot do this, so it also tells you what operation you used the
undefined value in. Note, however, that perl optimizes your program
anid the operation displayed in the warning may not necessarily appear
literally in your program. For example, "that $foo" is usually
optimized into "that " . $foo, and the warning will refer to the
concatenation (.) operator, even though there is no . in
your program.
Hi, I have following structure of my vhost files:
/etc/apache2/vhosts/user1/family.user1.com
/etc/apache2/vhosts/user1/thai.user1.com
/etc/apache2/vhosts/user1/valery.user1.com
/etc/apache2/vhosts/user2/user2.ru
in expand_included_files
you use following command to find files in directory:
# ls /etc/apache2/vhosts/* 2> /dev/null
/etc/apache2/vhosts/user1:
family.user1.com thai.user1.com valery.user1.com
/etc/apache2/vhosts/user2:
user2.ru
Look's like it should be **/*
to work as intended
# ls /etc/apache2/vhosts/**/*
/etc/apache2/vhosts/user1/family.user1.com /etc/apache2/vhosts/user1/valery.user1.com /etc/apache2/vhosts/user2/user2.ru
/etc/apache2/vhosts/user1/thai.user1.com
I'm running Ubuntu 16.04.1 LTS.
In comments
Version 1.0
It's been that for years
Let's just remove it
[ CRITICAL ] Going by the largest Apache process, Apache can potentially use 1125.31 MB RAM:
Without considering services: 113.67 % of total installed RAM <--- NOT RED
Considering extra services: 118.19 % of remaining RAM <--- NOT RED
[ WARNING ] Apache has a pending package update.
Ign http://mirror.rackspace.com jessie InRelease
Hit http://mirror.rackspace.com jessie/updates InRelease
Hit http://mirror.rackspace.com jessie Release.gpg
Hit http://mirror.rackspace.com jessie Release
Hit http://mirror.rackspace.com jessie/updates/main Sources
Hit http://mirror.rackspace.com jessie/updates/main amd64 Packages
Hit http://mirror.rackspace.com jessie/updates/main Translation-en
Hit http://mirror.rackspace.com jessie/main Sources
Hit http://mirror.rackspace.com jessie/main amd64 Packages
Hit http://mirror.rackspace.com jessie/main Translation-en
Reading package lists...
Looks like the mandatory apt-get update
we need to run prior to the check is actually dumping output into the variable, and stdout
Have been running apache2buddy.pl with PATH to run on cPanel/WHM hosts.
PATH=/usr/local/apache/bin/:$PATH ./apache2buddy.pl
The following adds cPanel's apache path to the apachectl lookup internally
*** 1285,1289 ****
# Check for which apachectl we are to use
# check to see if there is a binary called "apachectl" in our path
- our $apachectl= `which apachectl`;
+ our $apachectl= `PATH=/usr/local/apache/bin/:\$PATH which apachectl`;
chomp($apachectl);
For example output:
[ INFO] This apache webserver has 12 vhosts.
Potentially we could throw up a warning if they have more vhosts than maxclients!? eg
[ INFO] This apache webserver has 150 vhosts.
[ WARNING] The number of vhosts (150) exceeds maxclients (60)!
Example output might look like:
[ INFO ] Obtaining a count of directories in /var/www with 777 Permissions: 45647
[ INFO ] Obtaining a count of files in /var/www with 777 Permissions: 456497960
The check for php fatal errors needs to detect php-fpm and use /var/log/php-fpm/* instead of or as well as /var/log/httpd/*
Detecting PHP Fatal Errors....
PRO TIP: If this process appears to hang, press CTRL + c to exit the program, and then
go check for a large error log file in /var/log/httpd or /var/log/apache2.
grep: /var/log/httpd/fastcgi: Is a directory
[ OK ] No PHP Fatal Errors were found.
This particular server is running php-fpm...
# ls -la /var/log/php-fpm/
total 628
drwxrwx--- 2 apache apache 4096 Dec 4 04:21 .
drwxr-xr-x 13 root root 4096 Dec 8 04:26 ..
-rw------- 1 root root 191481 Dec 8 21:04 error.log
-rw------- 1 root root 26020 Nov 20 04:20 error.log-20161113.gz
-rw------- 1 root root 27895 Nov 27 04:33 error.log-20161120.gz
-rw------- 1 root root 41650 Dec 4 04:21 error.log-20161127.gz
-rw------- 1 root root 273387 Dec 4 04:11 error.log-20161204
-rw-r--r-- 1 <REDACTED> apache 8515 Dec 8 20:02 <REDACTED>.com-error.log
-rw-r--r-- 1 <REDACTED> apache 23268 Nov 20 04:20 <REDACTED>.com-error.log-20161113.gz
-rw-r--r-- 1 <REDACTED> apache 2382 Nov 27 04:33 <REDACTED>.com-error.log-20161120.gz
-rw-r--r-- 1 <REDACTED> apache 5008 Dec 4 04:21 <REDACTED>.com-error.log-20161127.gz
-rw-r--r-- 1 <REDACTED> apache 5193 Dec 3 23:53 <REDACTED>.com-error.log-20161204
Spotted this today by myself, while checking over a customer's server. Hence the redactions.
Working at the University we have some config that is system dependant so we are using environment variables to change paths but they are ignored while reading the conf files currently it seems.
Example:
<IFDefine RHE>
ServerRoot /etc/httpd
</IFDefine>
<IFDefine SUSE>
ServerRoot /etc/apache2
</IfDefine>
Any chance this can be parsed instead of scanned?
Hi,
I'm currect not sure if this is a bug but i'm getting wrong MPM information
Currectly i'm running prefork your script detect it all fine here.
The problem is the values is getting information from ITK instead of Prefork
[ INFO ] OS Name: CentOS
[ INFO ] OS Release: 6.8
[ OK ] Apache2buddy supports this OS Release/Version.
[ INFO ] We are checking the service running on port 80...
[ INFO ] The process listening on port 80 is nginx:
[ INFO ] The process running on port 80 is not Apache. Falling back to proce ss list...
[ INFO ] Apache is actually listening on port 8080
[ INFO ] The process running on port 8080 is Apache/2.2.15 (Unix).
[ INFO ] Apache has been running 4d 09h 45m 14s.
[ INFO ] The full path to the Apache config file is: /etc/httpd/conf/httpd.c onf
[ INFO ] Apache is using prefork model.
[ INFO ] pidfile setting is run/httpd.pid.
[ INFO ] Actual pidfile is /var/run/httpd/httpd.pid.
[ INFO ] Parent PID: 3608.
[ OK ] Memory usage of parent PID is less than 50MB: 10824 Kilobytes.
[ INFO ] Your server has 32129 MB of PHYSICAL memory.
[ INFO ] Your ServerLimit setting is 256.
[ INFO ] Your MaxClients setting is 256.
[ OK ] Current Apache Process Count is 54, including the parent PID.
[ INFO ] Number of vhosts detected: 5.
[ OK ] Current Apache vHost Count is less than maxclients.
[ INFO ] Your MaxRequestsPerChild setting is 4000.
Perfork setting is not that if not the ITK its report the same values.
[ CRITICAL ] Consider setting up a log rotation policy.
[ CRITICAL ] Note: Log rotation should already be set up under normal circumstances, so very
[ CRITICAL ] large error logs can indicate a fundmeneal issue with the website / web application.
This one really depends on the size of the logs because we know that large logs really impact the performanc of apache2buddy execution, so perhaps limit to the last 100,000 lines, remove date / timestamps and produce a nice report of the top 5 or 10 PHP Fatal errors recorded.
This might be invoked with a switch, and not displayed by default:
--show-php-fatal-errors
Example output might be:
Scanning Error Logs for PHP Fatal Errors, showing top 1 - 5:
================================================
123134 PHP Fatal Error: Missing Variable In file Blah on Line 15
23424 PHP Fatal Error: Call to an undeclared Function in File Foo on Line 87
545 PHP Fatal Error: Cannot assign a widget to a oojmaflop in function get_data() in file Bar on Line 123
Hello,
I'm getting the following error on different servers:
root@srv01:/tmp# curl -sL apache2buddy.pl | perl
Performing Auto-Discovery, and Pre-Flight Checks...
[ OK ] This script is being run as root.
[ OK ] The utility 'pmap' exists and is available for use: /usr/bin/pmap
[ OK ] 'php' exists and is available for use: /usr/bin/php
[ OK ] The port (port 80) is a valid port.
[ INFO ] We are attempting to discover the operating system type and version number ...
[ INFO ] OS Name: Debian
[ INFO ] OS Release: 8.2
[ OK ] The operating system is supported.
[ INFO ] Hostname:
[ INFO ] Primary IP:
[ INFO ] We are checking the service running on port 80...
[ INFO ] The process listening on port 80 is /usr/sbin/apache2
[ INFO ] The process running on port 80 is Apache/2.4.10 (Debian).
[ INFO ] Apache has been running 5d 03h 40m 32s.
[ INFO ] The full path to the Apache config file is: /etc/apache2/apache2.conf
[ INFO ] Apache is using prefork model.
Uncaught exception from user code:
Unable to open file:
main::find_included_files(ARRAY(0x1faa480), ARRAY(0x1faca28), "/etc/apache2") called at - line 314
main::build_config_array("/etc/apache2/apache2.conf", "/etc/apache2") called at - line 1529
main::preflight_checks() called at - line 1888
Do you have any ideas, what I could be missing?
Regards
[root@cb4-dev apache2buddy]# curl -sL apache2buddy.pl | perl - --report
[ WARNING ] *** LOW UPTIME ***.
[ ADVISORY ] The following recommendations may be misleading - apache has been restarted within the last 24 hours.
[ OK ] Current Apache Process Count is 6, including the parent PID.
[ INFO ] Number of vhosts detected: 0.
[ OK ] Current Apache vHost Count is less than maxrequestworkers.
[ ADVISORY ] vHost Count works only when we have NameVirtualHosting enabled, check config manually, they may only have the default vhost.
Detecting Control Panels...
[ INFO ] This server is NOT running Plesk.
[ INFO ] This server is NOT running cPanel.
[ OK ] No large logs files were found in /var/log/httpd.
[ OK ] No large logs files were found in /var/log/apache2.
[ OK ] No large logs files were found in /var/log/php-fpm.
Detecting Package Updates for Apache or PHP...
[ OK ] No package updates found.
[ ADVISORY ] I only checked for "apache specific" package updates (eg php, httpd, httpd24u, or apache2 packages only).
--------------------------------------------------------------------------------
Apache2buddy.pl report for server: cb4-dev (REDACTED):
Settings considered for this report:
[ WARNING ] *** LOW UPTIME ***.
[ ADVISORY ] The following recommendations may be misleading - apache has been restarted within the last 24 hours.
Your server's physical RAM: 987 MB
Remaining Memory after other services considered: 898 MB
Apache's MaxRequestWorkers directive: 150 <--------- Current Setting
Apache MPM Model: prefork
Your recommended MaxRequestWorkers setting is between 149 and 166. <------- Acceptable Range (10% of MAX)
Max potential memory usage: 811 MB
Percentage of TOTAL RAM allocated to Apache: 82.22 %
Percentage of REMAINING RAM allocated to Apache: 90.31 %
[root@REDACTED ~]# cat /etc/redhat-release
CentOS release 6.8 (Final)
[root@REDACTED ~]# curl -sL apache2buddy.pl | perl
Can't locate Time/HiRes.pm in @inc (@inc contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at - line 8.
BEGIN failed--compilation aborted at - line 8.
[root@REDACTED ~]#
code for red hat systems is already available here:
https://github.com/richardforth/checkbox4/commit/d59c0a95f8313d758f2d0c0bbfd4f5807ec7df16
best wait for the Debian . Ubuntu support to work before merging that function into this project
this will require a domain forwarding change, and a wrapper script, and workflow changes transparently for end users:
apache2buddy.pl forwards to a wrapper script (which must be written in perl*)
wrapper script checks md5 and sha26 sums
if both pass, the wrapper script launches apache2buddy.
if either of them fail to match, the wrapper script aborts execution
because this would then be transparent to people running:
# curl -sL apache2buddy.pl | perl
### GENERAL FINDINGS & RECOMMENDATIONS ###
--------------------------------------------------------------------------------
Apache2buddy.pl report for server: debian (REDACTED):
Settings considered for this report:
[ WARNING ] *** LOW UPTIME ***.
[ ADVISORY ] The following recommendations may be misleading - apache has been restarted within the last 24 hours.
Your server's physical RAM: 994 MB
Remaining Memory after other services considered: 994 MB
Apache's MaxRequestWorkers directive: 150 <--------- Current Setting
Apache MPM Model: prefork
Largest Apache process (by memory): 5 MB
[ !! ] Your MaxRequestWorkers setting is too low.
Your recommended MaxRequestWorkers setting is between 152 and 169. <------- Acceptable Range (10% of MAX)
Max potential memory usage: 880 MB
Percentage of TOTAL RAM allocated to Apache: 88.59 %
Percentage of REMAINING RAM allocated to Apache: 88.59 %
--------------------------------------------------------------------------------
This is really irritating.
Detecting additional services for consideration...
[ INFO ] MySQL Detected => Using 84.47 MB of memory.
I mean its not wrong as such because MariaDB is a drop in replacement (almost) but it plays on my OCD
# mysql
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 11
Server version: 5.5.52-MariaDB MariaDB Server
Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
Apache 2.4 MaxClients has been renamed to MaxRequestWorkers, this script is still using MaxClients
[ INFO ] pidfile setting is run/httpd.pid
[ CRITICAL ] Unable to open pid file /var/run/httpd/httpd.pid. Exiting.
https://wiki.debian.org/DebianReleases
} elsif ( $os_name eq "Debian" ) {
if ( $os_release <= 6.0 ) {
to
} elsif ( $os_name eq "Debian" ) {
if ( $os_release <= 7.0 ) {
Errors with "[ CRITICAL ] Either we couldnt get the OS name, or its not a supported distro."
As CloudLinux is based upon Centos Ive created this diff
*** 1333,1336 ****
--- 1333,1338 ----
if ( $os_name eq "CentOS" ) {
$os_release = `cat /etc/redhat-release 2>&1 | head -1 | awk '{ print \$3 }'`;
+ } elsif ( $os_name eq "CloudLinux" ) {
+ $os_release = `cat /etc/redhat-release 2>&1 | head -1 | awk '{ print \$3 }'`;
} elsif ( $os_name eq "Red" ) {
$os_name = `cat /etc/redhat-release 2>&1 | head -1 | awk '{ print \$1 " " \$2 " " \$3 " " \$4 }'`;
Now passes OS check
$ whois apache2buddy.pl
...
renewal date: 2017.04.08 10:09:23
which: no apachectl in (/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin)
[ INFO ] Unable to locate the apachectl utility. This script requires apachectl to analyze Apache's vhost configurations.
[ INFO ] Not fatal yet, trying to locate the apache2ctl utility instead.
which: no apache2ctl in (/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin)
[ INFO ] Unable to locate the apache2ctl utility. This script requires apache2ctl to analyze Apache's vhost configurations.
This bug was introduced when we started looking for vhosts. apachectl and / or apache2ctl became a requirement. and it no longer fails correctly by identifying that we may be running NGINX natively.
Note it will still run through fine if NGINX is a reverse proxy to apache on the same machine, however, in s purely native NGINX environment, we get this rather ungraceful death.
Suggested fix might look like:
which: no apachectl in (/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin)
[ INFO ] Unable to locate the apachectl utility. This script requires apachectl to analyze Apache's vhost configurations.
[ INFO ] Not fatal yet, trying to locate the apache2ctl utility instead.
which: no apache2ctl in (/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin)
[CRITICAL] Unable to locate the apache2ctl utility. This script requires apache2ctl to analyze Apache's vhost configurations.
[ INFO ] It looks like you might be running something else, other than apache.
or
which: no apachectl in (/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin)
[ INFO ] Unable to locate the apachectl utility. This script requires apachectl to analyze Apache's vhost configurations.
[ INFO ] Not fatal yet, trying to locate the apache2ctl utility instead.
which: no apache2ctl in (/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin)
[CRITICAL] Unable to locate the apache2ctl utility. This script requires apache2ctl to analyze Apache's vhost configurations.
[ INFO ] The service listening on port 80 is: NGINX (detect webserver here)
Added on Behalf of S. Waller
Arbitrary size chosen, , any additional thoughts?
[ INFO ] OS Name: Ubuntu
[ INFO ] OS Release: 14.04
...
Detecting additional services for consideration...
sh: 1: rpm: not found
[ INFO ] Detected => Using 1.20 MB of memory.
/var/www/vhosts//statistics/logs/
By default. One probably needs both of those pieces of information to make good decisions.
Hi, is possible to add suport for mpm-itk?
[ CRITICAL ] Unable to determine whether Apache is using worker or prefork
ii apache2-mpm-itk 2.2.22-13+deb7u7 amd64 multiuser MPM for Apache 2.2
Kind regards
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.