How Do You Troubleshoot the Sonar-Scanner Problem “java.lang.IllegalStateException: Unable to load component class org.sonar.scanner.scan.ProjectLock”?

Problem scenario
You run sonar-scanner from the command line.  You receive an error such as this:  "Error during SonarQube Scanner execution ... java.lang.IllegalStateException: Unable to load component class org.sonar.scanner.scan.ProjectLock at org.sonar.core.platform.ComponentContainer$ExtendedDefaultPicoContainer.getComponent(ComponentContainer.java.64"

What should you do?

Possible solution #1
Is the sonar-project.properties file in the directory from which you ran sonar-scanner?  This command expects this file to be in that directory.

Possible solution #2
Does the user that ran sonar-scanner have permissions to read sonar-project.properties?  This file needs to be readable.  You may need to use sudo before the sonar-scanner command or log in as a different user.

Possible solution #3
Does the sonar-project.properties file have a sonar.sources stanza?  If so is there a subdirectory that is at the same level as sonar-project.properties with the name assigned by the sonar.sources stanza?

If you see "sonar.sources=foobar", you would need a subdirectory named "foobar" in the directory with the sonar-project.properties file?

How Do You Use tar to Create a Single File That Is a Copy of a Subdirectory and All of Its Files and Subdirectories?

Problem scenario
You want to recursively copy subdirectories from on Linux machine to another.  How do you copy them into one file with the directory structure for the purpose of transferring it later?

Solution
On the source server go to the parent directory that you want to compress into one file.  Run this tar command:

tar cvfz target.tgz subdirsource/

Now target.tgz will have all the directories of  subdirsource.

# If you want to uncompress target.tgz, run this command from a directory where you can write to (e.g., have permissions to create subdirectories):

tar zxvf target.tgz

How Do You Get ansible-vault to Prompt You for a Password to Encrypt a File That You Create?

Problem scenario
You are using the ansible-vault command.  You are not being prompted for a password as the documentation suggests you would be.  You want to use ansible-vault create or ansible-vault edit and be prompted for a password. How can you specify a password manually?  How can someone on a different Ansible server decrypt your encrypted files?  

Possible solution #1
Modify the ansible.cfg file. Comment out a stanza like this:

# vault_password_file = ~/.vault_pass.txt

If there is no leading pound "#" mark, add one to comment it out.

Possible solution #2
Upgrade or downgrade Ansible from 2.4.  There is a documented bug about this.

Possible solution #3
When you run ansible-vault, use this flag: --ask-vault-pass

Here is an example:  ansible-vault create contint.yml --ask-vault-pass

What Should You Do It You See Duplicate Plugins in Jenkins List of “Available” Plugins?

Problem scenario
You log into Jenkins.  You go to Manage Jenkins -> Manage Plugins -> Available.   You see the same plugin listed twice (e.g, under different categories such as "Build Reports" or "External Site/Tool Integrations").  What should you do?

Solution
This is a workaround: look at the version of the plugins.  Are there duplicates the same version?  If the versions are the same, ignore one duplicate as we do not think it will cause a problem.  For convenience Jenkins displays plugins in different categories if the plugin is a member of two categories.

What Is the Python Requests Syntax Equivalent of a curl “-X DELETE”?

Problem scenario
You are invoking requests.get() in a Python program (after an "import requests" statement near the top of your code).  You want to pass the equivalent of "-X DELETE" in curl in your Python program.  How do you use the DELETE option with a REST API call in Python?

Solution
Prerequisites

This assumes you have "requests" installed (e.g., sudo pip install requests).  If you need assistance installing pip, see this link for Debian/Ubuntu, this link for a Linux SUSE server, and this link for CentOS/RHEL/Fedora.

Procedure
Use requests.delete() in your code.  This external page http://docs.python-requests.org/en/master/user/quickstart/ used to have more information.

How Do You Troubleshoot the SonarQube Problem “Service unavailable” in the Web UI?

Problem scenarios
Your situation is described in one of two ways.

#1  You go to the SonarQube web UI to log in.  You see nowhere to log in.  You see this error: "Service Unavailable    The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later."  What should you do?

Or your situation is like this:

#2  You have installed SonarQube and Apache web server.  You go to the SonarQube website and the error message in the web browser is "Service Unavailable."  You see some listening activity from the back-end.  The Sonar service is active.  

In the /var/log/httpd/ directory (the path may vary depending on how your web service is configured), the error log has entries like these:
"Connection refused: AH00957: HTTP: attempt to connect to...failed"

Why cannot you log into the web UI?  Why does the web UI logon page not load correctly?

Solution
Possible Solution #1

1.  Go to the back-end (the command prompt of the Linux server). 
2.  Go to the sonarqube directory (e.g., with conf, logs, and other subdirectories).  
3.  Go to logs.  Look at web.log.  
4.  Is the sonar.properties file in the conf subdirectory configured properly?  An incorrect password for the underlying SQL database could cause this problem.

Possible Solution #2
1.  Find the sonar*.conf file.  Use this command: sudo find / -name sonar*.conf
2.  See how it refers to the server (e.g., with localhost, the hostname, the internal IP address, the loopback IP address, the external IP address).  Is the reference to the server the same as the sonar.properties file for the sonar.web.host stanza?  This stanza should be consistent with the httpd.conf or apache2.conf file.
3.  To find the file you could run this command: sudo find / -name sonar.properties
4.  Then you could run this command: cat <resultFromPreviousCommand> | grep -i sonar.web.host
5.  Change the sonar.properties file so it uses the same reference to the server that the sonar*.conf file.

Possible Solution #3 (applicable if you use Apache web server with SonarQube)
1.  A server reboot may be an option.  If you do not do this, continue to step 2.  If you do reboot the server, skip to step 3.
2.  Start and stop the SonarQube service.

You may or may not do it with these two commands:
sudo systemctl sonar stop
sudo systemctl sonar start

Start and stop the Apache web server service.  You may or may not do it with these two commands:

sudo systemctl httpd stop
sudo systemctl httpd start

3.  Look at the /opt/sonarqube/temp/ directory.  Does the subdirectory "conf" have an owner root and group root?  If so, this is generally a sign of a problem.

If the "Service unavailable" problem persists look at your  /etc/systemd/system/sonar.service file.  Does it have these two stanzas?

User=root
Group=root

The "root" for user should be changed to the user who is the owner of the /opt/sonarqube directory.  The "root" for group should be changed to one of the groups for the user who is the owner of the /opt/sonarqube/ directory.  To find out the groups for that user, log in as that user.  Run the command "groups" to display those groups.  If you need to change the owner and groups of the /opt/sonarqube directory (and subdirectories and files), run this command:

sudo chown -R sonar:sonargroup # but change sonar and sonargroup as needed.

(Remember that just because you change it once does not mean that the .../temp/conf directory will retain those changes.  Cycling the Sonar services will change the ownership based on the sonar.service file's settings.)

4.  After you change the sonar.service file, run this command:  sudo system daemon-reload

Then restart the sonar and web services (as described in the above step 2).  You should be able to get to the web UI of SonarQube.  If you need to redeploy SonarQube, see this posting.

How Do You Troubleshoot PHP Not Displaying the Output of a Bash Command?

Problem scenario
You have a PHP program that works from the back-end (from a command terminal executing like php foobar.php). When you view the program in a web browser, it is not running the Bash commands properly. What should you do?

Solution
The root cause is probably the user execution context and a variety of permissions or configuration settings on the Linux system.

If the output of the Bash command is multiple lines, you may be capturing only the last line and sending that to a variable in PHP. If the last line was empty, you may see just white.

The user account that invokes the PHP program when it is executed via someone browsing to it on a web page is different from your back-end user account. This may be what is wrong. Here is one important diagnostic for you. Create a file called good.php and place it where a user can browse to it (e.g., /var/www/html/).

<?php
    $output = shell_exec('/usr/bin/env | /usr/bin/xargs');
    echo $output;
?>

<html>
<body>

HELLO!

</body>
</html>

When you go to the above web page in a web browser, you will get an idea of what issues your PHP program is running into when it is executed from someone browsing to it. (The apache or nginx users may be executing the PHP program; these users may not have sufficient back-end permissions on the Linux system.) You may need to change the location of the "env" executable in the program above; you could use which env to find the appropriate location. Here is another tip if Linux commands are not processing properly from a PHP program: the /tmp/ directory has the sticky bit set. So you should choose a different directory to write to. You may want to run sudo ls -lhd /foobar (where "foobar" is the destination directory where the bash script is supposed to write to).

How Do You Write to a File with Python?

Problem scenario
You want to store variable values in a log file.  How do you get Python to write to a log file?

Solution
Use these lines in your Python program:

var1 = 'contint'

with open('contint.log', 'a') as contint_log:
    contint_log.write("\n")  # creates a new line
    contint_log.write(var1)
    contint_log.write("Done writing variable.\n") # template text

How Do You Install SonarQube Scanner on a RHEL Server?

Update on 2/10/22: The Python example is a little dated. Back when Python 2.x was common, the print statements didn't necessarily have parentheses.

Problem scenario
SonarQube does not work without a launcher installed.  The web UI seems complete, but it is not.  You need a CLI launcher of some sort on the back-end.  You want to use sonar-scanner from the command prompt to analyze some code.  You have installed SonarQube and configured it so the web UI front end allows you to log in.  How do you install the sonar-scanner command line interface tool?

Solution
Prerequisites

i.  You must have SonarQube installed.  If you need directions, see this posting.

ii.  Install unzip if it is not already installed.  To install it, run this command: sudo yum -y install unzip

Procedures
1.  Download the .zip file from SonarQube's website.  (Go to the link.  Click on the link for the Community Edition if you do not want to pay and can agree to the terms.)

2.  Expand the .zip file in a directory of your choice on a Linux server.  You may want to move the .zip file to /opt/ and run this command:

sudo unzip sonar-scanner-cli*.zip

3.  Run this command:  ls

4.  Prepare (or draft) a command such as this, but replace "LastPart" with the last portion of the directory name of the new directory created from step #2 as displayed in step #3:  sudo mv sonar-scanner-LastPart sonar-scanner
Run this command once you prepare it.

5.  Go to /opt/sonar-scanner/conf

6.  Modify the sonar-scanner.properties file.  Uncomment out this line and replace "localhost" with the hostname of the server:

#sonar.host.url=http://localhost:9000

Replace 9000 with the port number you used if you used a non-default port number when you configured the sonar.properties file.

7.  In the /opt/sonar-scanner/conf directory, create a sonar-project.properties file.  Place the following content in it:

# "Contint" must be unique in a given SonarQube instance
sonar.projectKey=Contint
# "Contint" is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1.
sonar.projectName=Contint
sonar.projectVersion=1.0

# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
# This property is optional if sonar.modules is set.
sonar.sources=contint

8.  In the /opt/sonar-scanner/conf/ directory create a new directory called contint.  (If you want to have you sonar-scanner command look in a different directory for source code files to analyze, do not create the contint directory.  Modify the sonar-project.properties file so the stanza sonar.sources= stanza points to the location of your choice.)

Create a Python file and Java file in this directory.

Here is an example of a Java program called hello.java:

public class HelloWorld {

    public static void main(String[] args) {

        System.out.println("Hello, World");
    }

}

Here is an example of a Python program called hello.py:

var1 = 'hello'
print var1

9.  Run this command: sudo /opt/sonar-scanner/bin/sonar-scanner -X

10.  Open the web UI for SonarQube and log in.  If you are not using a web server the URL is often http://x.x.x.x:9000/sonar where x.x.x.x is the external IP address of the server.  The default credentials are usually admin / admin.  If you are using a web server (e.g., Apache web server), just go to http://x.x.x.x where x.x.x.x is the external IP address of the server.

11.  Go to "Projects" in the web UI.  You should see one called "Contint" if you followed the above directions (because of step #7).  Click on the hyperlink.

12.  Click on the directory called "contint" as it should be named as such because of step #8.  

13.  You should see the .java and .py files in the GUI now; these files were created in step #8.  You can click on "Issues" near the top to see more about what SonarQube has found with the code.  If you used the examples above, the hello.py file should cause a message about the print statement.  A preferred way of using the print statement is to put parentheses around the variable like this:

print(var)

14.  You are now done.

How Do You Capture Error Messages in a File of Your Choice Using Python Rather Than Have Them Printed to the Screen?

Problem scenario
You have a Python program that displays urllib3 (or some other type) of message to the screen.  You do not want them echoed there cluttering the screen.  You want to redirect the output to a log file (to permanently store the data).  How do you get a Python program to write to a log file?

Solution
Use these three lines, but replace "contint" with the name of your choice:

import logging

logging.basicConfig(filename='contint.log', filemode='a', level=logging.DEBUG)
logging.captureWarnings(True)