Monitor timeouts in TeamCity

TeamCity is a Continuous Integration (CI) tool that enables software development teams to build and test their software. Sometimes the server is too busy to serve the users and the web user interface does not respond in time. TeamCity logs all actions in a log file so we can find the date and time of these timeouts:

On Windows

  1. Remote into the TeamCity server,
  2. Open the server log file at D:\TeamCity\logs\teamcity-server.log

Scroll to the bottom of the file and search for “Request processing took too long” going up to find the last timeout event.

Native resolution in Remote Desktop client on MacOSX

When you connect to a Windows computer from your Macintosh workstation the best remote desktop client is the Microsoft Remote Desktop app from the Apple Appstore.

To configure the remote desktop connection for the best experience

  1. Select Native resolution
  2. Scale content for Full screen mode
    To be able to unselect the “Use all monitors checkbox”, uncheck it first, before you uncheck the “Start session in full screen” checkbox, otherwise, the last checkbox will be disabled.

If you use multiple displays, make sure you open the Microsoft Remote Desktop app on the display you want to use to view the remote computer, because the Native resolution setting will use the resolution of the display the app is running on at the moment you start the remote desktop connection.

How to move a window on the Macintosh if the header is not visible

There are times when a window opens on your Mac and the header is out of the screen or hiding behind the Macintosh Toolbar.

To show the toolbar

Option 1.

  1. Click the window to select it,
  2. Press Command 1 to switch the window to full-screen mode,
  3. Press Command 1 again to exit full-screen mode,
  4. The toolbar appears on the screen.

Option 2.

If the trick above does not work, try to find a point on the edge that instead of stretches the window, moves it. Four small regions on the sides can move the window up and down, another two small regions at the bottom can move the window sideways. The locations of the regions are very inconsistent, in one moment they work, a second later the region is at another location.

 

How to restore a Microsoft SQL database from backup with the Microsoft SQL Server Management Studio (MSSMS) user interface

There are multiple reasons to restore a database from backup. One of them can be disaster recovery, the other is to bring the production database to the developer machine. In both cases, the computer already has the old version of the database. In the new version of Microsoft SQL Server Management Studio (MSSMS) we cannot find the “Close connections” checkbox anymore, so we have to make sure all connections are closed, and we specify a unique database file name to restore the database to.

  1. On the developer machine close all instances of Visual Studio to close the open database connections,
  2. Close all Microsoft SQL Server Management Studio tabs that are connected to the database,
  3. Move the backup file to the C:\Temp folder. Microsoft SQL Server Management Studio cannot see it in your Downloads folder.
  4. Make sure your user account does not automatically connect to the database you want to restore:
    1. In Security, Logins right click your username and select Properties,
    2. Set the Default database to master
  5.  Disconnect from the database server:
    1.  Right-click the database server and select Disconnect,

  6. Connect to the database engine, but do not open the database you want to restore:
    1. Execute,
      USE Master
  7. Import the database from production with the user interface:
    1. Right-click the database and select Tasks, Restore, Files and Filegroups
    2. Select the From device radio button
    3. Click the button to select the backup file
    4. In the Select backup devices window click the Add button to select the file
    5. Navigate to the C:\Temp folder and select the database backup file
    6. Click the OK button
    7. In the Select the backup sets section select the Restore check box in the file row, and click Options on the left side,
    8. On the Options tab select the Overwrite existing database (WITH REPLACE) check box, and click the button to set the new unique database file name,
    9. Click OK to ignore the error message on the Locate Database Files – … message box
    10. Navigate to the current database file, click it, and append the date of the backup to the end of the file name to specify a unique data file name, and click OK,
    11. On the Restore Files and FileGroups window click the OK button to restore the database

Update the database to make it work at the new location

  1. On a development machine set the databases to Simple recovery mode, so the log files do not grow out of bound.
    ALTER DATABASE my_database SET RECOVERY SIMPLE;
  2. Delete and recreate the users in the restored database, because those have different internal IDs if the database was migrated from a different server
    USE my_database;
    GO
    spDropUser 'my_user', 'dbo'
    GO
    DROP SCHEMA my_user
    GO

    For some reason If I type DECLARE below, WordPress crashes. Please add the letter E to the end of the first word below.

    DECLAR @user_name varchar(50)
    SET @user_name = 'my_user'
    USE my_database; EXEC sp_grantdbaccess @user_name; EXEC sp_addrolemember @rolename = 'db_datareader', @membername = @user_name; EXEC sp_addrolemember @rolename = 'db_datawriter', @membername = @user_name; 
    GO

Error waiting for instance (i-…) to become ready: unexpected state ‘terminated’, wanted target ‘running’

When you launch a server instance with Terraform, sometimes the error message does not contain the underlying cause. When the cloud provider cannot complete the request, many times Terraform displays a generic error message:

Error waiting for instance (i-...) to become ready: unexpected state 'terminated', wanted target 'running'

To find the root cause of the error in AWS

  1. Log into the AWS console and navigate to the EC2 section,
  2. Search for the instance by the instance Id,
  3. You can find the error message at the bottom of the Description tab

In our specific case, it was Client.VolumeLimitExceeded: Volume limit exceeded

We had to increase the volume limit to be able to launch more large EC2 instances.

Upgrade a server on an AWS EC2 instance with minimum risk and downtime

When you need to upgrade an application on an AWS EC2 instance with minimum downtime, there are many options.

Upgrade an EC2 instance

  1. Stop the application, so users don’t make more changes,
  2. Create a backup of the database (snapshot of the RDS instance),
  3. Create a backup of the server (backup image of the EC2 instance),
  4. Upgrade the application on the server,
  5. Start the application,
  6. Test the new version of the application.

In case the upgrade fails, or the post-upgrade test fails

  1. Stop the application,
  2. If you use RightScale to launch servers:
    1. stop the RightLink service on the failed server to prevent RightScale auto terminating the restored server
      (When RightScale finds a new identical server instance, it automatically shuts it down to avoid multiple instances with the same identifier.)
    2. Terminate the failed server
  3. Stop the failed server,
  4. Restore the database from the pre-upgrade backup with a new name,
  5. Restore the server instance from the pre-upgrade backup,
  6. Start the restored server,
  7. Change the database address in the application’s config file to point to the restored database,
  8. Start the application,
  9. Test the restored version of the application.

To make the backup image of the AWS EC2 instance

  1. Open the AWS console and navigate to EC2, Running instances
  2. Find the server instance you want to backup
  3. Right-click the row of the instance and select Image, Create Image

  4. Name the image and click the Create Image button
  5. Save the image Id from the popup

Test your RightScale script without creating unnecessary revisions

There are certain functions in RightScale scripts (RightScripts) that you cannot test without launching a new instance. To test your script:

  1. Edit the Head revision of the RightScale script and save it,
  2. Attach the Head revision of the RightScale script to the Head revision of the RightScale Server Template,
    1. Select the Head revision of the server template, on the Scripts tab click the Modify button
    2. Click the rev dropdown next to the script’s name and select head
  3. In your Self Service CAT file reference revision 0 (zero) of the Server Template (Head revision),
    ( “server_template_revision”  => “0”, )
  4. Upload the Self Service CAT file to Self Service, but do not publish it,
  5. Launch a server instance from Self Service using the RightScale Self-Service Designer page, not the Catalog.

If the script has some errors, modify the Head revision of the RightScale script and launch a new server instance using the RightScale Self-Service Designer page.

When the script works perfectly:

  1. Commit the RightScale script, creating a new RightScale script revision,
  2. Attach the committed revision of the RightScale script to the Server Template’s Head revision,
  3. Commit the Server Template, creating a new Server Template revision,
  4. Publish the new revision of the Server Template,
  5. Reference the new revision of the Server Template in your Self Service CAT file.

Custom Git Status and Git Pull commands to work with all of your repositories

If you work with many Git repositories it is easy to miss a repository when you commit your changes, and very time consuming to pull from all repositories.

It is easy to automate both processes.

In this example, we will place all files in the ~/Git/devops-scripts folder. If you want to place your files at another location change it in the files below.


\/  \/  \/  \/  \/  \/  \/  \/  \/  \/

In Windows

To find your home directory on a Windows workstation, open a Bash window (Git Bash) and execute

echo ~

/\  /\  /\  /\  /\  /\  /\  /\  /\  /\


Create the Bash script files

  • Create a file with the list of Git repositories and save it as ~/Git/devops-scripts/git-repositories.txt
    You can separate groups of repositories with empty lines.
# Local_Path+Remote_Path+Rename_the_folder_to(optional)
~/Git/MY_REPO1+https://github.com/MY_REPO1.git+RENAME_TO1
~/Git/MY_REPO2+https://github.com/MY_REPO2.git

~/Git/MY_REPO3+https://github.com/MY_REPO3.git
  • Create a file to check the status of all Git repositories and save it as ~/Git/devops-scripts/git-status.sh
#!/bin/bash

# git-status.sh
# Shows the GIT STATUS of the Git repositories and shows the recommended actions
# The list is in git-repositories.txt

eval input="~/Git/devops-scripts/git-repositories.txt" # Need EVAL, otherwise the Bash loop cannot interpret ~ as the home directory if the path contains ~

RED='\033[0;31m'
NC='\033[0m' # No Color

while IFS= read -r folder
do

 # Get the length of the path
 # On Windows the empty line manifests itself as a 1 character long not empty string
 path_length=${#folder}

 if [[ ( -n "$folder" ) ]] && [[ ( 1 < $path_length ) ]] ; then
 # The path is not empty and the length is greater than 1

 # Ignore the lines starting with #
 if [[ ! $folder == \#* ]] ; then
 # The line is not a comment, process it

 # Split the local and remote path
 eval local_path=$(echo "$folder" | cut -f1 -d+) # Need EVAL, otherwise the IF statement below does not work if the path contains ~
 remote_path=$(echo "$folder" | cut -f2 -d+)

 if [ ! -d "$local_path" ]
 then

 # The local directory doesn't exist.
 echo -e "${RED}$local_path does not exist, PULL to get $remote_path${NC}"

 else

 eval cd $local_path # Need EVAL, otherwise CD does not work if the path contains ~
 pwd | tr -d '\n'

 status=$(git status)

 # --------------------------------------------------------------------------
 # To handle

 # On branch master
 # Your branch is up-to-date with 'origin/master'.
 # Untracked files:
 # (use "git add <file>..." to include in what will be committed)

 if [[ $status == *"Untracked files"* ]]; then
 echo -e " ---- ${RED}New files added, please ADD${NC}" | tr -d '\n' # -e tells echo to enable backslash escapes
 fi

 # --------------------------------------------------------------------------
 # To handle

 # On branch master
 # Your branch is up-to-date with 'origin/master'.
 # Changes not staged for commit:
 # (use "git add <file>..." to update what will be committed)
 # (use "git checkout -- <file>..." to discard changes in working directory)

 if [[ $status == *"Changes not staged for commit"* ]]; then
 echo -e " ---- ${RED}Files changed, please ADD${NC}" | tr -d '\n' # -e tells echo to enable backslash escapes
 fi

 # --------------------------------------------------------------------------
 # To handle

 # On branch master
 # Your branch is up-to-date with 'origin/master'.
 # Changes to be committed:
 # (use "git reset HEAD <file>..." to unstage)

 if [[ $status == *"Changes to be committed"* ]]; then
 echo -e " ---- ${RED}Please COMMIT${NC}" | tr -d '\n' # -e tells echo to enable backslash escapes
 fi

 # --------------------------------------------------------------------------
 # To handle

 # On branch master
 # Your branch is ahead of 'origin/master' by 1 commit.
 # (use "git push" to publish your local commits)
 # nothing to commit, working tree clean

 if [[ $status == *"git push"* ]]; then
 echo -e " ---- ${RED}Please PUSH${NC}" | tr -d '\n' # -e tells echo to enable backslash escapes
 fi

 # --------------------------------------------------------------------------
 # To handle

 # On branch master
 # Your branch and 'origin/master' have diverged,
 # and have 1 and 1 different commits each, respectively.
 # (use "git pull" to merge the remote branch into yours)
 # nothing to commit, working tree clean

 if [[ $status == *"git pull"* ]]; then
 echo -e " ---- ${RED}Repos diverged, PULL to merge${NC}" | tr -d '\n' # -e tells echo to enable backslash escapes
 fi

 # --------------------------------------------------------------------------

 echo

 fi

 fi

 fi
done < "$input"
  • Create a file to pull from all Git repositories and save it as ~/Git/devops-scripts/git-pull.sh
#!/bin/bash

# git-pull.sh
# Pulls Git repositories and clones the missing ones
# The list is in git-repositories.txt

eval input="~/Git/devops-scripts/git-repositories.txt" # Need EVAL, otherwise the Bash loop cannot interpret ~ as the home directory if the path contains ~

RED='\033[0;31m'
NC='\033[0m' # No Color

while IFS= read -r folder
do

 # Get the length of the path
 # On Windows the empty line manifests itself as a 1 character long not empty string
 path_length=${#folder}

 if [[ ( -n "$folder" ) ]] && [[ ( 1 < $path_length ) ]] ; then
 # The path is not empty and the length is greater than 1

 # Ignore the lines starting with #
 if [[ ! $folder == \#* ]] ; then
 # The line is not a comment, process it

 # Split the local and remote path
 eval local_path=$(echo "$folder" | cut -f1 -d+) # Need EVAL, otherwise the IF statement below does not work if the path contains ~
 remote_path=$(echo "$folder" | cut -f2 -d+)
 rename_folder_to=$(echo "$folder" | cut -f3 -d+)

 # Check if the local path exists
 if [ ! -d "$local_path" ]; then
 # The local directory doesn't exist.
 echo
 echo -e "${RED}$local_path does not exist, cloning $remote_path${NC}"

 # Get the parent directory name
 parent_dir="${local_path%/*}"

 # Create the parent directory
 mkdir -p $parent_dir

 # Go to the parent_dir
 cd $parent_dir

 # Clone the Git repository
 git clone $remote_path

 if [[ ( -n "$rename_folder_to" ) ]] ; then

 # Rename the folder if necessary
 end_of_url="${remote_path##*/}"
 filename="${end_of_url%.*}"

 echo -e "${RED}Renaming $filename to $rename_folder_to${NC}"

 mv $filename $rename_folder_to

 fi


 else
 echo
 eval cd $local_path # Need EVAL, otherwise CD does not work if the path contains ~
 pwd
 git pull

 fi

 fi

 fi

done < "$input"

Enable the script execution


\/  \/  \/  \/  \/  \/  \/  \/  \/  \/

 In Mac OS

  • Open a terminal window in the ~/Git/devops-scripts folder
  • Run these commands to enable the execution of the Bash files
chmod u+x git-status.sh
chmod u+x git-pull.sh

/\  /\  /\  /\  /\  /\  /\  /\  /\  /\


Create an alias

Aliases allow you to execute commands from any folder in the command line and hide the complexity of the entire command.


\/  \/  \/  \/  \/  \/  \/  \/  \/  \/

In Mac OS

If you use the iTerm terminal window

iTerm reads the configuration settings from the~/.zshrc file. If you use iTerm add the alias definitions to the end of the ~/.zshrc file.

  • Open the~/.zshrc file and add the lines below to the end of it
If you use the built-in OSX Terminal

The built-in Terminal windows reads the configuration settings from the~/.bash_profile file.

  • Open the ~/.bash_profile file and add the lines below to it

In Windows

If you use Git Bash
  • Navigate to your home directory ( cd ~ )
  • Create the Bash config file if does not exist
    cp > ~/.bashrc

    Bash will show the “cp: missing file operand” an error message, but it will create the file that you can edit with any text editor

  • Add the lines below to the file

/\  /\  /\  /\  /\  /\  /\  /\  /\  /\


 

alias status='~/Git/devops-scripts/git-status.sh'
alias pull='~/Git/devops-scripts/git-pull.sh'

Refresh the settings in the Bash shell environment


\/  \/  \/  \/  \/  \/  \/  \/  \/  \/

In MacOS

source ~/.bash_profile

In Windows

Close the Bash window and open it again

/\  /\  /\  /\  /\  /\  /\  /\  /\  /\


How to use it

Open a terminal window in any folder

To check if you need to add, commit or push files in a Git repository:

status

If you have added new files to the repository you get:

/Users/YOUR_USER_NAME/Git/devops-scripts —- New files added, please ADD

If you have changed files in a Git repository you get:

/Users/YOUR_USER_NAME/Git/devops-scripts —- Files changed, please ADD

If you have already executed the git add . command, but have not yet committed the changes:

/Users/YOUR_USER_NAME/Git/devops-scripts—- Please COMMIT

If you have already committed the changes, but have not pushed the to the remote repository:

/Users/YOUR_USER_NAME/Git/devops-scripts —- Please PUSH

To pull from every Git repository before you start to work and clone the missing ones

pull

 

 

Useful Bash commands

Most of these commands work in all Linux, MacOSX, and Unix shells, but some of them only work in selected shells.

Find files recursively by file name pattern

find . -name '*.MY_EXTENSION'

Find files, but exclude a directory from the search. (The -print is needed at the end of the line)

find . -path ./tmp/windows -prune -o -name '*.MY_EXTENSION' -print

Get the absolute path of files recursively

find `pwd` -name MY_FILENAME

Delete files recursively by file name pattern

Works in zsh but not in sh or bash.
New versions of bash cannot do this by default only if the shell option globstar is enabled:
shopt -s globstar
The globbing pattern is **/*.o but that is not limited to files.

find . -type f -name '*.MY_EXTENSION' -delete

Make a shell script file executable

chmod u+x FILE_NAME.sh

Directory Listing

Sort by date, most recent on top

ls -lt

Sort by date oldest on top

ls -ltr

Sort by date, display only last modification date and file name

ls -lt | awk '{print $7,$8,$9, $10}'

Display the CHMOD numbers in the output of the ls command

ls -l | awk '{k=0;for(i=0;i<=8;i++)k+=((substr($1,i+2,1)~/[rwx]/) \
 *2^(8-i));if(k)printf("%0o ",k);print}'

Generate a public SSH key from the private key

ssh-keygen -y -f PRIVATE_KEY_FILE.pem > PUBLIC_KEY_FILE.pub

Replace all spaces in every filename and directory name recursively with dash

find . -name “* *” -print0 | sort -rz | \
while read -d $’\0′ f; do mv -v “$f” “$(dirname “$f”)/$(basename “${f// /-}”)”; done

To check if a package is installed

# For RHEL 
rpm -qa *MY_SEARCH_TERM*
# For Ubuntu
dpkg —list | grep MY_PACKAGE_NAME

Security and user management

Add a user to a Linux user group

To add your user account to a user group

sudo usermod -aG THE_GROUP_NAME $USER 

To add another user to a group

sudo usermod -aG THE_GROUP_NAME THE_USER_NAME 

Windows 10 can’t connect to this network

If your Windows 10 computer can successfully connect to some wireless networks, but cannot connect to certain wireless networks, it is possible, that the stored credentials are out of date. To force Windows 10 to ask you for the updated username and password

  1. In the Start Menu select Settings,
     
  2. On the Windows Settings page select Network & Internet,
  3. On the left side select Wi-Fi,
  4. On the Wi-Fi page select Manage known networks,
  5. Select the network you are not able to connect and click the Forget button,
  6. In the lower right corner of the screen select the Wi-Fi network icon, select the network, and click the Connect button.