Showing posts with label Centos. Show all posts
Showing posts with label Centos. Show all posts

Saturday, July 31, 2021

Upgrade Nginx on CentOS/RHEL 7 from 1.16.1/1.15.2 to 1.20.1, install with Ansible

The upgrade of Nginx on CentOS/RHEL 7 from 1.16.1/1.15.2 to 1.20.1 involved a complete manual removal and ansible installation.  Complete removal and installation were used vs upgrading the version because upgrading requires Nginx modules to be upgraded separately, where an installation takes care of everything.

NOTES:

  • In my case, there were no breaking changes with the nginx.conf and cherryshoe.conf files used from the old to new versions.
  • I installed with yum several times, and on occasion the /etc/nginx/conf.d and /etc/nginx/default.d folders were not created.  You may have to add the ansible task to create these for you prior to copying over the configuration files.
Environment:
ansible 2.9.9
CentOS/RHEL 7
nginx 1.16.1/1.15.2 to 1.20.1

Uninstall existing Nginx

  1. change to the appropriate user that has access to sudo
  2. note the old version, should be 1.16.1/1.15.2
    • nginx -v
  3. stop nginx and verify it's down
    • sudo systemctl stop nginx
    • sudo systemctl status nginx
  4. remove nginx
    • sudo yum remove nginx
    • Confirm y
    • Should see something like the following:
      Loaded plugins: fastestmirror
      Repodata is over 2 weeks old. Install yum-cron? Or run: yum makecache fast
      Resolving Dependencies
      --> Running transaction check
      ---> Package nginx.x86_64 1:1.16.1-1.el7 will be erased
      --> Processing Dependency: nginx for package: 1:nginx-mod-http-xslt-filter-1.16.1-1.el7.x86_64
      --> Processing Dependency: nginx for package: 1:nginx-mod-http-perl-1.16.1-1.el7.x86_64
      --> Processing Dependency: nginx for package: 1:nginx-mod-stream-1.16.1-1.el7.x86_64
      --> Processing Dependency: nginx for package: 1:nginx-mod-mail-1.16.1-1.el7.x86_64
      --> Processing Dependency: nginx for package: 1:nginx-mod-http-image-filter-1.16.1-1.el7.x86_64
      --> Running transaction check
      ---> Package nginx-mod-http-image-filter.x86_64 1:1.16.1-1.el7 will be erased
      --> Processing Dependency: nginx-mod-http-image-filter = 1:1.16.1-1.el7 for package: 1:nginx-all-modules-1.16.1-1.el7.noarch
      ---> Package nginx-mod-http-perl.x86_64 1:1.16.1-1.el7 will be erased
      ---> Package nginx-mod-http-xslt-filter.x86_64 1:1.16.1-1.el7 will be erased
      ---> Package nginx-mod-mail.x86_64 1:1.16.1-1.el7 will be erased
      ---> Package nginx-mod-stream.x86_64 1:1.16.1-1.el7 will be erased
      --> Running transaction check
      ---> Package nginx-all-modules.noarch 1:1.16.1-1.el7 will be erased
      --> Finished Dependency Resolution
      Dependencies Resolved
      ==========================================================================================
      Package                            Arch          Version               Repository    Size
      ===========================================================================================
      Removing:
       nginx                              x86_64        1:1.16.1-1.el7        @epel        1.6 M
      Removing for dependencies:
       nginx-all-modules                  noarch        1:1.16.1-1.el7        @epel        0.0
       nginx-mod-http-image-filter        x86_64        1:1.16.1-1.el7        @epel         24 k
       nginx-mod-http-perl                x86_64        1:1.16.1-1.el7        @epel         54 k
       nginx-mod-http-xslt-filter         x86_64        1:1.16.1-1.el7        @epel         24 k
       nginx-mod-mail                     x86_64        1:1.16.1-1.el7        @epel         99 k
       nginx-mod-stream                   x86_64        1:1.16.1-1.el7        @epel        171 k
      Transaction Summary
      ===========================================================================================
      Remove  1 Package (+6 Dependent packages)
       Installed size: 2.0 M
      Is this ok [y/N]:
      
  5. delete nginx configuration and log folders
    • sudo rm -R /etc/nginx
    • sudo rm -R /var/log/nginx

Install Nginx

The ansible deploy will install nginx-1.20.1, task looks like:

The upgrade of Nginx on CentOS/RHEL 7 from 1.16.1/1.15.2 to 1.20.1 involved a complete manual removal and ansible installation.  Complete removal and installation were used vs upgrading the version because upgrading requires Nginx modules to be upgraded separately, where an installation takes care of everything.

NOTES:

  • In my case, there were no breaking changes with the nginx.conf and cherryshoe.conf files used from the old to new versions.
  • I installed with yum several times, and on occasion the /etc/nginx/conf.d and /etc/nginx/default.d folders were not created.  You may have to add the ansible task to create these for you prior to copying over the configuration files.

Uninstall existing Nginx

  1. change to the appropriate user that has access to sudo
  2. note the old version, should be 1.16.1/1.15.2
    • nginx -v
  3. stop nginx and verify it's down
    • sudo systemctl stop nginx
    • sudo systemctl status nginx
  4. remove nginx
    • sudo yum remove nginx
    • Confirm y
    • Should see something like the following:
  5. delete nginx configuration and log folders
    • sudo rm -R /etc/nginx
    • sudo rm -R /var/log/nginx

Install Nginx

The ansible deploy will install nginx-1.20.1, task looks like:

- name: install system dependencies
  yum:
    name:
      - nginx-1.20.1
    state: present
    update_cache: yes

- block:
    - name: set up nginx site conf
      template:
        src: "{{ item.src }}"
        dest: "{{ item.dest }}"
      with_items:
        - { src: "cherryshoe.conf.j2", dest: "/etc/nginx/conf.d/cherryshoe.conf" }
        - { src: "nginx.conf.j2", dest: "/etc/nginx/nginx.conf" }
    - name: restart nginx
      systemd: enabled=yes state=reloaded name=nginx

Verification

  1. verify new version
    • nginx -v
  2. verify nginx configuration and log folders created
    • sudo ls -la /etc/nginx
    • sudo ls -la /var/log/nginx
  3. verify application works

Friday, December 4, 2020

Docker Compose - change COMPOSE_HTTP_TIMEOUT and verify env_file environment variable configuration options

I occasionally get the below error while running docker-compose on my local VM or while running on Jenkins.

ERROR: for cherryshoe_test_ta_run_609fc9bdd396  UnixHTTPConnectionPool(host='localhost', port=None): Read timed out. (read timeout=60)
An HTTP request took too long to complete. Retry with --verbose to obtain debug information.
If you encounter this issue regularly because of slow network conditions, consider setting COMPOSE_HTTP_TIMEOUT to a higher value (current value: 60).

Environment:
CentOS Linux release 7.3.1611 (Core)
Docker version 19.03.1, build 74b1e89

You can verify this environment variable with the docker-compose config command, which prints the resolved application config to the terminal, by accessing the environment variable in the docker-compose file.   A sample docker-compose yml below is used to test this out:

docker-compose-cs.yml
version: "3"
services:
  cherryshoe:
    image: "testconfig:${COMPOSE_HTTP_TIMEOUT}"

The config command verifies the default COMPOSE_HTTP_TIMEOUT value of 60:

$ docker-compose -f docker-compose-cs.yml config
services:
  cherryshoe:
    image: testconfig:60
version: '3.0'

After using the env_file to set the value to a higher number,

.env

#.env file for docker-compose.  Use same file for all environments.
# set COMPOSE_HTTP_TIMEOUT at docker instance level and not inside docker image.
COMPOSE_HTTP_TIMEOUT=120

run the config command again to verify it:

$ docker-compose -f docker-compose-cs.yml config
services:
  cherryshoe:
    image: testconfig:120
version: '3.0'

This article was helpful.


Tuesday, November 10, 2020

Docker - enabling systemd on centos:7

I'm experimenting with enabling systemd on the docker centos:7 image.  Here's a simple example getting the centos7 systemd image set up, then building a docker image with nginx using that, and then running it.  

Environment:
CentOS Linux release 7.3.1611 (Core)
Docker version 19.03.1, build 74b1e89

centos7-systemd.Dockerfile

# systemd is included with centos:7 but not enabled by default - START
# https://hub.docker.com/_/centos:
FROM centos:7
ENV container docker
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == \
systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;
VOLUME [ "/sys/fs/cgroup" ]
CMD ["/usr/sbin/init"]
# systemd is included with centos:7 but not enabled by default - END

centos7-systemd-nginx.Dockerfile

# This dockerfile is used when running cypress during a commit to the remote repo
FROM local/centos7-systemd

# install yum dependencies ansible
RUN yum install -y epel-release \
  && yum install -y nginx && systemctl enable nginx.service

EXPOSE 80

CMD ["/usr/sbin/init"]

Build images:

docker build --rm -t local/centos7-systemd -f centos7-systemd.Dockerfile .
docker build -t local/centos7-systemd-nginx -f centos7-systemd-nginx.Dockerfile .

Run container:

docker run -it --rm -d -v /sys/fs/cgroup:/sys/fs/cgroup:ro -v /run -p 80:80 --name web local/centos7-systemd-nginx

Test that nginx is running: 

curl http://localhost/index.html

It returned an error HTML page, but I know nginx is running!

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
    <head>
        <title>The page is not found</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <style type="text/css">
            /*<![CDATA[*/
            body {
                background-color: #fff;
                color: #000;
                font-size: 0.9em;
                font-family: sans-serif,helvetica;
                margin: 0;
                padding: 0;
            }
            :link {
                color: #c00;
            }
            :visited {
                color: #c00;
            }
            a:hover {
                color: #f50;
            }
            h1 {
                text-align: center;
                margin: 0;
                padding: 0.6em 2em 0.4em;
                background-color: #294172;
                color: #fff;
                font-weight: normal;
                font-size: 1.75em;
                border-bottom: 2px solid #000;
            }
            h1 strong {
                font-weight: bold;
                font-size: 1.5em;
            }
            h2 {
                text-align: center;
                background-color: #3C6EB4;
                font-size: 1.1em;
                font-weight: bold;
                color: #fff;
                margin: 0;
                padding: 0.5em;
                border-bottom: 2px solid #294172;
            }
            h3 {
                text-align: center;
                background-color: #ff0000;
                padding: 0.5em;
                color: #fff;
            }
            hr {
                display: none;
            }
            .content {
                padding: 1em 5em;
            }
            .alert {
                border: 2px solid #000;
            }
            img {
                border: 2px solid #fff;
                padding: 2px;
                margin: 2px;
            }
            a:hover img {
                border: 2px solid #294172;
            }
            .logos {
                margin: 1em;
                text-align: center;
            }
            /*]]>*/
        </style>
    </head>
    
    <body>
        <h1><strong>nginx error!</strong></h1>
        <div class="content">
            <h3>The page you are looking for is not found.</h3>
            <div class="alert">
                <h2>Website Administrator</h2>
                <div class="content">
                    <p>Something has triggered missing webpage on your
                    website. This is the default 404 error page for
                    <strong>nginx</strong> that is distributed with
                    Fedora.  It is located
                    <tt>/usr/share/nginx/html/404.html</tt></p>

                    <p>You should customize this error page for your own
                    site or edit the <tt>error_page</tt> directive in
                    the <strong>nginx</strong> configuration file
                    <tt>/etc/nginx/nginx.conf</tt>.</p>

                </div>
            </div>

            <div class="logos">
                <a href="http://nginx.net/"><img
                    src="/nginx-logo.png"
                    alt="[ Powered by nginx ]"
                    width="121" height="32" /></a>

                <a href="http://fedoraproject.org/"><img
                    src="/poweredby.png"
                    alt="[ Powered by Fedora ]"
                    width="88" height="31" /></a>
            </div>
        </div>
    </body>
</html>

These articles were helpful:
https://hub.docker.com/_/centos
https://stackoverflow.com/questions/36617368/docker-centos-7-with-systemctl-failed-to-mount-tmpfs-cgroup

Tuesday, April 21, 2020

Setting up redis with Node.js

I recently setup redis for the application I'm working on.  Because database records could take multiple hours to complete, the user has access to past requests by a unique identifier and can get subsequent results in seconds vs. hours.

The redis server setup was done with an ansible yum module, which installed an older version 3.2.12, but it was adequate for my needs so I pinned it at that version.

Environment:
CentOS Linux release 7.3.1611 (Core)
node v8.16.0
redis server 3.2.12
redis 3.0.2 (client)

I verified with redis-cli that the redis server was installed appropriately:
redis-cli ping (should return PONG)
redis-cli --version (should return redis-cli 3.2.12)
keys * (gets all keys)
set hello world
get hello

I realized for my use case it would be advantageous to set an expire time/time to live for the keys.  You can practice this on command line first:
pttl hello (should return (integer) -1 since expire time/time to live wasn't set)
set foo bar ex 10 (expires in 10 seconds)
get foo (before expired)
pttl foo (should return a non-negative integer since expire time/time to live set)
get foo (after expired will return (nil))
del foo

Then I worked on client-side code to support this.  This is the client module that any other module can import and use.

cacheClient.js module
const redis = require("redis");
const client = redis.createClient();

// Node Redis currently doesn't natively support promises, however can wrap the methods with
// promises using the built-in Node.js
const { promisify } = require("util");
const getCacheAsync = promisify(client.get).bind(client);

const DEFAULT_TTL_SECONDS = 60*60*24*5; // 5 days time to live

/**
 * Client will emit error when encountering an error connecting to the Redis server or when any
 * other in Node Redis occurs.  This is the only event type that the tool asks you to provide a
 * listener for.
 */
client.on('error', function(error) {
  console.error(`Redis client error - ${error}`);
});

/**
 * Adds key with value string to cache, wiith number of seconds to live.
 * @param {String} key
 * @param {String} value
 * @param {int} seconds: default is 5 days
 */
function addToCache(key, value, seconds = DEFAULT_TTL_SECONDS) {
  console.log(`Cache add hash[${key}]`);
  // EX sets the specified expire time, in seconds.
  client.set(key, value, 'EX', seconds);
}

/**
 * Retrieves value with key.
 * @param {String} key
 * @returns {String}
 */
async function getFromCache(key) {
  const val = await getCacheAsync(key);
  if (val) {
    console.log(`Cache retrieve hash[${key}]`);
  }
  return val;
}

module.exports = {
  addToCache,
  getFromCache,
};

Then I tested locally.
1.  I made the max size of the cache very small (2MB), and I added two keys with two separate unique requests with a time to live of 5 days.  I then added the 3rd one, and I verified the older one was deleted to fit the new one
- backup /etc/redis.conf
- edit /etc/redis.conf maxmemory 2mb
- restart - sudo systemctl restart redis
- check maxmemory took by issuing the following in redis-cli
    - config get maxmemory
- check time to live for keys by issuing the following in redis-cli
   - pttl <key>
- add keys with requests
- check memory information by issuing the following in redis-cli
   - info memory
2.   I had several keys in the cache, and we went on spring break, by the time I got back to work 5 days had gone by and my keys had been expired and no longer in the cache

I then went back to custom configure with ansible what I needed for redis, which were the following redis.conf changes.
1.  Ensured /etc/redis dir exists in order to copy the default template /etc/redis.conf to it
2.  Copied template config to /etc/redis/redis.conf
3.  For the greatest level of data safety, run both persistence methods, so needed to enable append-only logs of all write operations performed by the redis server (AOF)
4.  Enable daemonize so redis server will keep running in the background
5.  Configure cache max memory (default out-of-the-box is no max)
6.  Configure cache eviction policy (default out-of-the-box is no eviction)
7.  Updated systemd to use custom config file and reloaded systemd

Number 5 and 6 together were key; if these two are not custom configured, it's possible to hit a RAM max and error out in your application!!

More commands that are useful:
info keyspace (summary of num keys, num keys with expire set, average ttl)
flushall (deletes all keys from existing database)
redis-cli --scan --pattern "CS_*" | xargs redis-cli del (flush only keys that start with)
redis-cli --scan | xargs -L1 redis-cli persist (make all keys persistent)
redis-cli --bigkeys (sample Redis keys looking for big keys)
echo 'GET CS_12345' | redis-cli > CS_12345_value.txt (save key value to file)

Delete command for redis in cluster mode if running on 3 different ports:
redis-cli -c -p 6379 --scan --pattern "cst*" | xargs -L 1 redis-cli -c -p 6379 del
redis-cli -c -p 7001 --scan --pattern "cst*" | xargs -L 1 redis-cli -c -p 7001 del
redis-cli -c -p 7002 --scan --pattern "cst*" | xargs -L 1 redis-cli -c -p 7002 del
Good article that said delete keys one by one.

Friday, July 26, 2019

Culmination of hodgepodge realizations of WebSockets (Circa July 2019)

I've read many articles about WebSockets the past month, and each article gives one to several tidbits of information, but not enough to answer all my questions.

Environment:
CentOS Linux release 7.3.1611 (Core)
node v8.16.0
nginx version: nginx/1.12.2

Here's the culmination of what I've learned so far.  I am using Node.js with Express, "ws" for the Node WebSocket library, and native WebSocket javascript for the front-end.

  1. So many articles to read!  Some of the early articles I read taught how to code WebSocket connections, frames, listeners, etc yourself!  This is good reference but definitely not ideal to actually do! There's many libraries out there that can do this for you  I eventually chose "ws" as I discussed in my last post.
    • The only con I see right now it doesn't have a fallback method to long-polling like some libraries available (i.e. socket.io).   This doesn't concern me because WebSockets are supported by all major browsers - please reference number 7 below for more thoughts.
  2. Not explicitly clear if you are supposed to keep client connections open and re-use them as needed (or open a new one for each request).  
    • The typical use case for keeping client connection open and re-use them is for a chat type of application.
    • My use case (where I am opening a WebSocket connection each request) is that "occasionally" there will be requests that take "longer than usual", and where it used to be HTTP there would be a HTTP response timeout on the web server level (set at 5 mins).  To not have to keep increasing this timeout, a different solution was needed - polling, WebSockets, etc.  WebSockets were chosen for several reasons which I won't go into here.
  3. The Node backend is clustered with one instance per CPU, and a WebSocket Server is running alongside each Node Server instance, so it can handle many WebSocket client connections concurrently.  If you want a large number multiple concurrent WebSocket connections concurrently, take a look at this article.
  4. The WebSocket protocol discusses the concept of ping/pong messages for the server to know each client is still connected, as well as conversely each client connection can still communicate with the server (i.e. Wifi connection terminated unexpectedly):
    • If the WebSocket Server sends a ping or pong, then the client should have to be able to recognize a ping/pong was sent, and respond, but there is no client side javascript code that can send or recognize/receive ping/pong frames, it's either supported by the browser or not.  
      • As referenced from this article - “ping/pong frames” are used to check the connection, sent from the server, the browser responds to these automatically. 
      • This article was helpful in teaching me that "Unfortunately, the Websocket protocol does not provide a similar method for the client, to find out if it is still connected to the server. This can happen, if the connection simply disappears without further notification. In order to have the client recognize this, some Javascript code has to be added to the client code responsible for the Websocket".
      • Since my application controls both client and server code, adding in a specific header/metadata in a web socket message with `WebSocket#send()` vs using `WebSocket#ping()` can be used to implement a heartbeat. 
        • This article - helped me build a heartbeat system with messages.
      • During server development testing, I noticed that the heartbeat message was sometimes sent to the client and sometimes not:
        • Noticed that if paused in debugger, the setInterval function used for sending a heartbeat message from server -> client wasn't working, since the worker that is paused (so the heartbeat from server -> client is NOT sent).
        • If setTimeout(sleep) function was enabled (simulating actual work being perform), the setInterval check DOES RUN for the worker (so the heartbeat from server -> client is sent).
  5. Web Server configuration needs configuration to:
  6. This repo had a great explanation of all the various WebSocket libraries out there.
  7. WebSockets are supported by all the major browser,  but Internet Explorer (11) still has a default maximum number of client connections at 6.
  8. Easiest to understand guide were the WebSockets API documentation by mozilla.org.

Saturday, April 20, 2019

Changing Data Directory for MySQL on CentOS7

I was recently asked to move the DEV and TEST environment of the application I am working on to  new servers.  The old servers were running CentOS6, new servers running on CentOS7 with SELinux enabled.  I realized after the fact that the server that is hosting MySQL had a separate /data volume that had much disk space on it, so I needed to change the data directory after several databases had already been instantiated.

Environment:
CentOS Linux release 7.6.1810 (Core) with SELinux enabled with enforcing
Server version: 5.7.25 MySQL Community Server (GPL)

1.  Login as a user that has root privileges, sudo to root

2.  Verify the current data directory
mysql -u root -p <enter in the root password>

mysql> select @@datadir;
+-----------------+
| @@datadir       |
+-----------------+
| /var/lib/mysql/ |
+-----------------+
1 row in set (0.01 sec)

3. Stop mysqld and verify it is stopped
systemctl stop mysqld
systemctl status mysqld

Apr 19 08:39:51 <servername> systemd[1]: Stopping MySQL Server...
Apr 19 08:39:55 <servername> systemd[1]: Stopped MySQL Server.

4.  Check if you have cp with the -a option
man cp

       -a, --archive
              same as -dR --preserve=all
       -d     same as --no-dereference --preserve=links
       --preserve[=ATTR_LIST]
              preserve the specified attributes (default: mode,ownership,timestamps), if possible  additional  attributes:  context, links, xattr, all
       -R, -r, --recursive
              copy directories recursively

Copies a directory exactly as it is (preserves ownership and groups), the files retain all their attributes, and symlinks are not dereferenced (-d).

5.  The new folder/volume I want to copy to is /data..  Copy the files from the source /var/lib/mysql to /data with -a option
cp -a /var/lib/mysql /data

6. Rename the current folder /var/lib/mysql to a different name to avoid confusion
mv /var/lib/mysql /var/lib/mysql-OLD

7.  Take a backup of the my.cnf file
cp /etc/my.cnf ~/my.cnf.ORIG

8.  Configure MySQL data directory to new folder location, add in port=3306, and configure datadir and socket to the new location. Also add a [client] group to the bottom of the file (after every options in the [mysqld] group) with port and socket matching the [mysqld] group.

vi /etc/my.cnf

[mysqld]
port=3306
datadir=/data/mysql
socket=/data/mysql/mysql.sock

[client]
port=3306
socket=/data/mysql/mysql.sock

9.  Add SELinux security context to the new folder.  semanageutility is not installed by default and was missing, so installed policycoreutils-python.  Perform a listing with security context.

yum -y install policycoreutils-python
semanage fcontext -a -t mysqld_db_t "/data(/.*)?"
restorecon -Rv /data

ls -lZ /data/mysql/
ls -lZ /var/lib/mysql-OLD

NOTE:  If you don't perform this step, you will see the following warnings/errors in the /var/log/mysqld.log file.

2019-04-19T13:31:39.698773Z 0 [Warning] Can't create test file /data/mysql/<servername>.lower-test
2019-04-19T13:31:39.837948Z 0 [ERROR] InnoDB: The error means mysqld does not have the access rights to the directory.

9. Restart mysql
systemctl start mysqld
systemctl status mysqld

10.  Verify the new data directory
mysql -u root -p <enter in the root password>

mysql> select @@datadir;
+-----------------+
| @@datadir       |
+-----------------+
| /data/mysql/ |
+-----------------+
1 row in set (0.01 sec)

These articles helped a lot:

Friday, April 22, 2016

Bash scripting - replace URLs for different environments

Unfortunately, due to limitations of the project, a better solution for environment specific settings was not available.  I wrote a bash script to perform automated deployment of a front end angular web application.  There was a client-side javascript file that needed a specific environment specific URL.

Below is the sed command I used inside the bash script to do this.  Instead of using a backslash as the delimiter, I used #, you can use another non-character as well.

Environments tested
CentOS release 6.7

To replace "https://localhost:8080" with "http://dev.cherryshoetech.com" in the cherryshoetech.js file:
  • When you don't need to use shell variables, the following works:
sed -i 's#https://localhost:8080#http://dev.cherryshoetech.com#g' cherryshoetech.js
  • When you need to use shell variables, the following works.  Notice the double quotes are used for interpolation:
sed -i "s#$OLD_ENVIRONMENT_URL#$NEW_ENVIRONMENT_URL#g" cherryshoetech.js

Also used the following to grep for specific process "gulp" and kill in the same line.  This article was of great help.
kill $(ps aux | grep '[g]ulp' | awk '{print $2}')


Thursday, December 24, 2015

CentOS - How to uninstall package installed by rpm

I had installed openvpn via rpm on my CentOS 6.5 OS.  To uninstall it, you must know the exact package name.
  1. Issue "rpm -qa" and grep for what your package name may contain
    • $ rpm -qa | grep openvpn
      openvpn-as-2.0.20-CentOS6.4.x86_64
  2. Issue rpm -e to remove the exact package name
    • $ sudo rpm -e openvpn-as-2.0.20-CentOS6.4.x86_64

Sunday, August 24, 2014

Centos hostname with dash causes configuration and tns issues with Oracle Express

Bottom Line:
When setting up a VirtualBox Centos VM that will eventually run Oracle Express, do NOT name the hostname with a dash in the name!

What Happened:
  • I set up a Centos 6.5 Virtual Box VM with the hostname of jhsu-cherryshoe; note the dash in the hostname.
  • I later installed Oracle Express 11g Release 2 for Linux x64 on it, and when configuring Oracle with /etc/init.d/oracle-xe configure, oracle did not complete its configuration properly.  Googling found some forums that said dashes in a Centos hostname may or may not cause issues with Oracle installs.
  • I went ahead and changed the hostname to jhsucherryshoe(no dash!) with the following instructions:
    • Run the hostname command
      • hostname jhsucherryshoe
    • Open /etc/sysconfig/network, update the HOSTNAME line and save:
      • # vim /etc/sysconfig/network
      • HOSTNAME=jhsucherryshoe
    • Open /etc/hosts file, and update the hostname entry and save: 
      • # vim /etc/hosts
      • 127.0.0.1 jhsucherryshoe
  • Running oracle configuration with /etc/init.d/oracle-xe configure again worked this time. Confirmed oracle started, sqlplus / as sysdba worked, and created a new db and user.
  • I thought this was the end of it and that all was well.  WRONG.
  • A couple days later I needed to access the db on the VM from my host machine with sqlDeveloper and could not access it.
  • The VirtualBox VM had the Network Adapter set to "Bridged Adapter", and the firewall configuration for the oracle port 1521 was configured so it wasn't an issue with network configs.
  • Errors seen on the VM:
    • "tnsping" gave tnslistener error
    • "lsnrctl stat" gave the following snippet.  
      • Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC_FOR_XE))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=jhsu-cherryshoe)(PORT=1521))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=jhsu-cherryshoe)(PORT=8081))(Presentation=HTTP)(Session=RAW))
    • Doing a grep in the /u01/app/oracle folder for jhsu-cherryshoe returned lots of results!  DARN missed that when renaming the hostname!  The initial install of the oracle rpm already created the configuration files with the original bad hostname in it. 
Final Solution for the issue of centos hostname with dash causing issues with Oracle:

  • Hostname for Centos was already changed previously
  • Uninstalled oracle xe, this article helped a lot:
    • Find out what oracle rpm's are installed
      • rpm -qa | grep oracle returned "oracle-xe-11.2.0-1.0.x86_64"
    • Uninstall the rpm via rpm -e <package name>
      • rpm -e oracle-xe-11.2.0-1.0.x86_64
    • Check the following files to makes ure oracle-xe was really uninstalled:
      • rm -Rf /usr/lib/oracle/xe
      • rm -Rf /etc/oratab
      • rm -Rf /etc/init.d/oracle-xe
      • rm -Rf /etc/sysconfig/oracle-xe
    • Installed oracle rpm again, configured, and now was able to access the DB from my host with sqlDeveloper
For more examples and ideas, I encourage you explore the links provided throughout this blog. What questions do you have about this post? Let me know in the comments section below, and I will answer each one.