├── README.md ├── RST5733SC1.CLP ├── SAV5733SC1.CLP ├── acsautomation ├── accessclientsolutions_dataxfer.pdf └── readme.md ├── bashprompt.md ├── createibmisampletables.md ├── curlcommandexamples.md ├── exportrdisettings.md ├── ibm_nfs_setup.md ├── ibmi_acs_odbcssl_linux_issue.md ├── ibmi_acs_odbcssl_mac_issue.md ├── ibmi_acs_odbcssl_windows_issue_.md ├── ibmi_afp_overlays_pagesegments.md ├── ibmi_default_profile_settings.md ├── ibmi_install_amazon_cli_v1.md ├── ibmi_mount_nfs_share.md ├── ibmi_set_default_shell.md ├── ibmi_shells.md ├── ibmigccgetstarted.md ├── ibmiperl.md ├── ibmisecuresshsetup.md ├── ibmisqlsamples.md ├── ibmisqlserverfreetds.md ├── ibmisshserverportconfig.md ├── ileastic-build-qshell.md ├── install-python-ibmivirtual-environment.md ├── install-rsync-daemon-onibmi.md ├── installcronie.md ├── installgitbucketonibmi.md ├── installgunicornibmi.md ├── installmariadbonibmi.md ├── installmkdocsibmi.md ├── installpostgresonibmi.md ├── installpythonfastapi.md ├── installwikijs.md ├── linuxcommands.md ├── nginx-ibmi-without-allobject-auth.md ├── nodejs20_register.md ├── postgres-backup-restore.md ├── pythonpipibmi.md ├── pythonwebgitvieweribmi.md ├── richard-favoritetools.md ├── setdefaultpaseuser.md ├── setup-office65-email-apppassword.md ├── tmux-howto.md ├── tn5250keys.md ├── update-alternatives-ibmi.md ├── use_ssh_keys_ibmi.md ├── usefulmacapps.md ├── windows └── batfile-timestamps.md └── writelogmessagefromstoredprocedure.md /README.md: -------------------------------------------------------------------------------- 1 | # Howto Stuff 2 | This is a general list of how-to items. 3 | 4 | # List of Examples 5 | 6 | Installing Python Web Based IFS Git Repository Viewer on IBM i 7 | https://github.com/richardschoen/howtostuff/blob/master/pythonwebgitvieweribmi.md 8 | 9 | How to set up IBM i Access ODBC Driver for Windows to use an SSL Certificate 10 | https://github.com/richardschoen/howtostuff/blob/master/ibmi_acs_odbcssl_windows_issue_.md 11 | -------------------------------------------------------------------------------- /RST5733SC1.CLP: -------------------------------------------------------------------------------- 1 | /* Restore 5733CS1 *BASE and option 1 */ 2 | PGM 3 | 4 | MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERRORS)) 5 | 6 | /* Create temp save files */ 7 | CRTSAVF FILE(QTEMP/Q5733SC1B) TEXT('5733SC1 - *BASE + 8 | option') 9 | MONMSG MSGID(CPF0000) 10 | CRTSAVF FILE(QTEMP/Q5733SC11) TEXT('5733SC1 - option + 11 | 1') 12 | MONMSG MSGID(CPF0000) 13 | 14 | /* Clear the saves file now */ 15 | CLRSAVF FILE(QTEMP/Q5733SC1B) 16 | CLRSAVF FILE(QTEMP/Q5733SC11) 17 | 18 | /* Copy from IFS to save files */ 19 | CPYFRMSTMF FROMSTMF('/tmp/q5733sc1b.savf') + 20 | TOMBR('/QSYS.LIB/QTEMP.LIB/Q5733SC1B.FILE') + 21 | MBROPT(*REPLACE) CVTDTA(*NONE) 22 | CPYFRMSTMF FROMSTMF('/tmp/q5733sc11.savf') + 23 | TOMBR('/QSYS.LIB/QTEMP.LIB/Q5733SC11.FILE') + 24 | MBROPT(*REPLACE) CVTDTA(*NONE) 25 | 26 | /* Restore 5733SC1 licensed program from save files */ 27 | RSTLICPGM LICPGM(5733SC1) DEV(*SAVF) OPTION(*BASE) + 28 | SAVF(QTEMP/Q5733SC1B) 29 | RSTLICPGM LICPGM(5733SC1) DEV(*SAVF) OPTION(1) + 30 | SAVF(QTEMP/Q5733SC11) 31 | 32 | RETURN 33 | 34 | ERRORS: 35 | SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Errors + 36 | occurred while restoring licensed program.') + 37 | MSGTYPE(*ESCAPE) 38 | 39 | ENDPGM 40 | -------------------------------------------------------------------------------- /SAV5733SC1.CLP: -------------------------------------------------------------------------------- 1 | /* Save 5733CS1 *BASE and option 1 */ 2 | PGM 3 | 4 | MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERRORS)) 5 | 6 | /* Create temp save files */ 7 | CRTSAVF FILE(QTEMP/Q5733SC1B) TEXT('5733SC1 - *BASE + 8 | option') 9 | MONMSG MSGID(CPF0000) 10 | CRTSAVF FILE(QTEMP/Q5733SC11) TEXT('5733SC1 - option + 11 | 1') 12 | MONMSG MSGID(CPF0000) 13 | 14 | /* Clear the saves file now */ 15 | CLRSAVF FILE(QTEMP/Q5733SC1B) 16 | CLRSAVF FILE(QTEMP/Q5733SC11) 17 | 18 | /* Save 5733SC1 licensed program */ 19 | SAVLICPGM LICPGM(5733SC1) DEV(*SAVF) OPTION(*BASE) + 20 | SAVF(QTEMP/Q5733SC1B) TGTRLS(*CURRENT) + 21 | LICACPRQD(*NO) 22 | SAVLICPGM LICPGM(5733SC1) DEV(*SAVF) OPTION(1) + 23 | SAVF(QTEMP/Q5733SC11) TGTRLS(*CURRENT) + 24 | LICACPRQD(*NO) 25 | 26 | /* Copy save files to IFS */ 27 | CPYTOSTMF + 28 | FROMMBR('/QSYS.LIB/QTEMP.LIB/Q5733SC1B.FILE+ 29 | ') TOSTMF('/tmp/q5733sc1b.savf') + 30 | STMFOPT(*REPLACE) CVTDTA(*NONE) 31 | CPYTOSTMF + 32 | FROMMBR('/QSYS.LIB/QTEMP.LIB/Q5733SC11.FILE+ 33 | ') TOSTMF('/tmp/q5733sc11.savf') + 34 | STMFOPT(*REPLACE) CVTDTA(*NONE) 35 | 36 | RETURN 37 | 38 | ERRORS: 39 | SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Errors + 40 | occurred while saving licensed program.') + 41 | MSGTYPE(*ESCAPE) 42 | 43 | ENDPGM 44 | -------------------------------------------------------------------------------- /acsautomation/accessclientsolutions_dataxfer.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/richardschoen/howtostuff/c843f2518d2e740ed71a0277df41f62fb577c4ed/acsautomation/accessclientsolutions_dataxfer.pdf -------------------------------------------------------------------------------- /acsautomation/readme.md: -------------------------------------------------------------------------------- 1 | # Automating IBM i ACS Uploads and Downloads 2 | This area covers how to automate uploads and downloads with IBM i Access Client Solutions and the Java based ```acsbundle.jar``` file. 3 | 4 | As part of IBM Access Client Solutions you have the ability to use ```acsbundle.jar``` to automatically file uploads and downloads using the file upload/download capabilities. 5 | 6 | You can download directly to Excel or CSV. 7 | 8 | You can upload from Excel or CSV as long as you have saved your transfer definition field definitions to an ```.fdfx``` file. 9 | 10 | Saved **file download request definitions** get saved to files ending in ```.dtfx```. 11 | 12 | Saved **file upload request definitions** get saved to files ending in ```.dttx```. 13 | 14 | ## General steps to set up a file download or upload profile 15 | 16 | ### Create a working copy of QIWS/QCUSTCDT to QIWS/QCUSTUPLD for testing 17 | ``` 18 | CPYF FROMFILE(QIWS/QCUSTCDT) 19 | TOFILE(QIWS/QCUSTUPLD) 20 | MBROPT(*REPLACE) 21 | CRTFILE(*YES) 22 | ``` 23 | 24 | ### Use ACS Data Transfer to Download, Upload and set up definition files 25 | image 26 | 27 | ### Install acsbundle.jar file to IFS 28 | Install the ```acsbundle.jar``` file into IFS directory ```/acsautomation```. 29 | 30 | ### File download request profile - .dtfx 31 | If you want to set up an automated download, you need to use the ```Data Transfer``` option in IBM i Access Client Solutions and save your download definition to a ```.dtfx``` file. You should also save the field definitions to a ```.fdfx``` file if you plan to upload data from an Excel or CSV file in the IFS. Copy your request definition file (.dtfx) and field definition file (.fdfx) to an IFS folder where you would like to run the profile from. 32 | 33 | ### File upload request profile - .dttx 34 | If you want to set up an automated upload, you need to use the ```Data Transfer``` option in IBM i Access Client Solutions to do an upload and then save your download definition to a ```.dttx``` file. You should also specify a previously saved field definition ```.fdfx``` file since it's required with Excel uploads and possibly CSV uploads as well. Copy your request definition file (.dttx) and field definition file (.fdfx) to an IFS folder where you would like to run the profile from. 35 | 36 | ## Links 37 | IBM documentation on using ACS upload and download 38 | https://www.ibm.com/support/pages/ibm-i-access-acs-getting-started 39 | 40 | Ocean Presentation on ACS 41 | https://www.oceanusergroup.org/assets/accessclientsolutions_dataxfer.pdf 42 | 43 | ## Files 44 | **accessclientsolutions_dataxfer.pdf** - Craig Pelkie Ocean presentation on ACS - 2012 45 | 46 | 47 | ## QShell on i Examples using QSHEXEC command 48 | 49 | ### Run an SQL Select statement and output to Excel file in the IFS 50 | Set DSPSTDOUT(*YES) to see stdout log info if you are testing interactivly. 51 | Use a transfer request file stored in ```/acsautomation/profiles```. 52 | ``` 53 | QSHEXEC CMDLINE('cd /acsautomation;java -jar acsbundle.jar 54 | /PLUGIN=cldownload /system=localhost /userid=USER1 55 | /sql="select * from qiws.qcustcdt" /clientfile=/tmp/test.xlsx') 56 | DSPSTDOUT(*NO) 57 | ``` 58 | 59 | ### Download physical file QIWS/QCUSTCDT to Excel file using Data Transfer Request File 60 | Set DSPSTDOUT(*YES) to see stdout log info if you are testing interactivly. 61 | Use a transfer request file stored in ```/acsautomation/profiles```. 62 | File to download and field definition file name (.fdfx) names stored in the (.dtfx) file. 63 | ``` 64 | QSHEXEC CMDLINE('cd /acsautomation;java -jar acsbundle.jar 65 | /PLUGIN=download /acsautomation/profiles/testout.dtfx') 66 | DSPSTDOUT(*NO) 67 | ``` 68 | 69 | 70 | ### Upload Excel file from IFS to physical file QIWS/QCUSTCDT using Data Transfer Request File 71 | Set DSPSTDOUT(*YES) to see stdout log info if you are testing interactivly. 72 | Use a transfer request file stored in ```/acsautomation/profiles```. 73 | File to upload and field definition file name (.fdfx) names stored in the (.dttx) file. 74 | ``` 75 | QSHEXEC CMDLINE('cd /acsautomation;java -jar acsbundle.jar 76 | /PLUGIN=upload /acsautomation/profiles/testout.dttx') 77 | DSPSTDOUT(*NO) 78 | ``` 79 | 80 | -------------------------------------------------------------------------------- /bashprompt.md: -------------------------------------------------------------------------------- 1 | # Customize your bash prompt for PASE or Linux command line 2 | This customizes your bash prompt. 3 | 4 | You can also google for: ```customize bash command prompt``` 5 | 6 | Add the following to your ```.bash_profile``` or ```.bashrc``` files. 7 | 8 | This example creates this prompt: ```user1@sys1:~$``` 9 | 10 | ``` 11 | PS1="\[\033[32m\]\u\[\033[0m\]@\[\033[34m\]\h\[\033[0m\]:\w\$ " 12 | export PS1 13 | ```` 14 | 15 | The following example creates this prompt: 16 | ![image](https://github.com/user-attachments/assets/a04a34e4-225b-4a16-b82b-378e5c636336) 17 | 18 | ``` 19 | PS1="\n\[\e[0;32m\]┌─[\[\e[0m\]\[\e[1;33m\]\u\[\e[0m\]\[\e[1;32m\] @ \[\e[0m\]\[\e[1;33m\]\h\[\e[0m\]\[\e[0;32m\]]─[\[\e[0m\]\[\e[1;34m\]\w\[\e[0m\]\[\e[0;32m\]]\[\e[0;32m\]─[\[\e[0m\]\[\e[0;31m\]\!\[\e[0m\]\[\e[0;32m\]]\[\e[0m\]\n\[\e[0;32m\]└─[\[\e[0m\]\[\e[1;37m\]\$\[\e[0m\]\[\e[0;32m\]]› \[\e[0m\]" 20 | ``` 21 | The [503] is the bash history line that can be used to re-run the bash command from history by its line number. 22 | 23 | ![image](https://github.com/user-attachments/assets/eb56f73a-515a-4c25-a4cc-ef06b80288f8) 24 | 25 | ![image](https://github.com/user-attachments/assets/a37d8485-db22-4ea2-95e8-33048dd6e704) 26 | 27 | ## Links to customize bash prompts 28 | https://phoenixnap.com/kb/change-bash-prompt-linux 29 | https://wiki.archlinux.org/title/Bash/Prompt_customization 30 | -------------------------------------------------------------------------------- /createibmisampletables.md: -------------------------------------------------------------------------------- 1 | # Create IBM i DB2 Sample Database Tables 2 | The following commands can be run from IBM ACS Run SQL Scripts to create a sample IBM i library with sample DB2 tables in it. 3 | 4 | Visit this IBM i site for info on the sample tables: 5 | 6 | https://www.ibm.com/docs/en/i/7.3?topic=reference-db2-i-sample-tables 7 | 8 | Create sample IBM i database tables in a library called **SAMPLE** 9 | 10 | ```CALL QSYS.CREATE_SQL_SAMPLE ('SAMPLE')``` 11 | 12 | Create sample IBM i database tables that contain embedded XML in a library called **SAMPLE** 13 | 14 | ```CALL QSYS.CREATE_XML_SAMPLE ('SAMPLE')``` 15 | 16 | After the SAMPLE library has been created the tables should exist. You can check with the following command 17 | 18 | ```WRKOBJPDM SAMPLE``` 19 | 20 | Sample SQL query to select data from customer table in SAMPLE library 21 | 22 | ``` 23 | select * from sample/customer 24 | -or- 25 | select * from sample.customer 26 | ``` 27 | -------------------------------------------------------------------------------- /curlcommandexamples.md: -------------------------------------------------------------------------------- 1 | # curl command line examples 2 | This document lists some sample curl command examples. These can be run from a bash command line on in conjunction with the QSHEXEC command from the QSHONI library on IBM i. http://www.github.com/richardschoen/qshoni 3 | 4 | The bash command line samples should also be compatible with Linux and other platforms, just remove the path qualifier (/QOpenSys/pkgs/bin) when not using IBM i. The reason I used the path qualifier is that if an older version of curl is loaded on the IBM i machine, it will get picked up by QShell or PASE, so we want to make sure we call the version in /QOpenSys/pkgs/bin always on IBM i. 5 | 6 | ## Sample bash command line to download a save file of the QSHONI library with binary contents intact 7 | ``` 8 | /QOpenSys/pkgs/bin/curl -o /tmp/qshoni.savf -LJO https://github.com/richardschoen/QshOni/releases/download/V1.0.2/qshoni.sav 9 | ``` 10 | 11 | ## Sample QSHEXEC command line to download a save file of the QSHONI library with binary contents intact 12 | ``` 13 | QSHONI/QSHEXEC 14 | CMDLINE('/QOpenSys/pkgs/bin/curl -o /tmp/qshoni.savf -LJO 15 | https://github.com/richardschoen/QshOni/releases/download/V1.0.2/qshoni.savf') 16 | DSPSTDOUT(*YES) PRTSTDOUT(*YES) PRTSPLF(CURLLOG) 17 | ``` 18 | 19 | # Curl documentation 20 | 21 | Curl manual page 22 | https://curl.se/docs/manpage.html 23 | 24 | How to Use Curl Command with Examples 25 | https://linoxide.com/tools/how-to-use-curl-command/ 26 | 27 | If you google: ***how to use curl*** you will find many other example sites for using curl. 28 | 29 | Let me know by posting in the issues if you have a cool command combination to share. 30 | 31 | -------------------------------------------------------------------------------- /exportrdisettings.md: -------------------------------------------------------------------------------- 1 | # Export and Import Rational Developer Settings (RDI) 2 | 3 | You may want to move Rational Developer for i (RDI) settings to another PC. Here's how: 4 | 5 | ## Export RDI Settings 6 | To export current user config settings: 7 | ``` 8 | Start RDI and select File/Export 9 | Select Rational Developer for i/Configuration Files and click Next 10 | Select All and click Next (Or you can select just the Remote System Artifacts) 11 | Specify file name. Ex: c:\temp\rdiconfig.cfg 12 | Click Finish to complete the export. 13 | ``` 14 | 15 | ## Import RDI Settings 16 | To import config settings: 17 | ``` 18 | Start RDI and select File/Import 19 | Select Rational Developer for i/Configuration Files and click Next 20 | Specify file name. Ex: c:\temp\rdiconfig.cfg 21 | Click Finish to complete the import. 22 | ``` 23 | -------------------------------------------------------------------------------- /ibm_nfs_setup.md: -------------------------------------------------------------------------------- 1 | # Setting up the IBM i Network File System (NFS) 2 | This document contains a list of useful NFS links. 3 | 4 | You can also use Navigator for i, just right-click on "NFS" in "TCP/IP Servers": 5 | 6 | ![image](https://github.com/user-attachments/assets/91905c09-7de4-4cf0-abbb-4fcad24b34fa) 7 | 8 | 9 | - IBM i Network File System (NFS) Documentation 10 | https://www.ibm.com/docs/en/i/7.5?topic=systems-network-file-system-nfs 11 | 12 | - IBM NFS Presentation 13 | https://www.ibm.com/support/pages/nfs-presentation 14 | https://www.ibm.com/support/pages/node/642587 15 | 16 | - Exploring NFS Redbook 17 | https://www.ibm.com/support/pages/system/files/support/nas/nastech.nsf/0/7e62ebc50008583085257bc1006af241/$FILE/Exploring%20NFS.sg24-5128.pdf 18 | 19 | - Share Files with UNIX Systems Through AS/400 NFS 20 | https://www.mcpressonline.com/operating-systems/unix-aix/share-files-with-unix-systems-through-as400-nfs 21 | -------------------------------------------------------------------------------- /ibmi_acs_odbcssl_linux_issue.md: -------------------------------------------------------------------------------- 1 | # How to set up IBM i Access ODBC Driver for Linux to use an SSL Certificate 2 | ```This article is not a full tutorial on setting up SSL on your IBM i. It covers the issue I had after SSL was set up and ODBC still was giving the CWBCO1050 certificate not trusted error on Linux.``` 3 | 4 | Installing and using the ```IBM i Access Client Solutions``` Java based software (which provides 5250, File Transfer IFS, Run SQL utilities, etc) and the Linux ODBC driver which is installed with the ```ACS Linux App Pkg``` is usually a pretty easy process. 5 | 6 | There are two separate installers for: ```IBM i Access Client Solutions``` and ```ACS Linux App Pkg``` available from the following download site if you have an IBM login: 7 | https://www.ibm.com/support/pages/ibm-i-access-client-solutions 8 | 9 | After installation and configuration you can usually configure a Telnet session with Access Client Solutions or create and use an ODBC data source without issues. 10 | 11 | ***Until you want to use SSL to connect to your database via ODBC instead of unsecured access......*** 12 | 13 | I was trying to set up my IBM i Access ODBC Driver with SSL on a Linux machine and every time I ran: 14 | ```cwbping mysysname /ssl:1``` to test SSL connectivity for the ODBC driver I got the following error: ```Error message CWBCO1050 - "The system certificate is not trusted".``` 15 | I got the same errors from the isql utility if I defined an ODBC data source with the ```SSL=1``` setting. 16 | Ex isql command to connect: ```isql -v mysysname user1 pass1``` 17 | 18 | **If you don't get an error from cwbping, there's nothing more to do. Your SSL is working.** 19 | 20 | My regular IBM i Access services (Java) such as Telnet were working fine with SSL, so I knew the issue had to be with the Linux based ODBC drivers (different technology - C/C++) and its need to use a different certificate store for SSL certs. Apparently on Linux, trusted certificate files need to be located in the following directory: ```/usr/local/share/ca-certificates``` 21 | 22 | Using the ```Key Management``` option from IBM i Access Client Solutions, I exported the trusted certificate file I wanted Linux to trust and saved it to a file. In this example we'll say we exported it to file: ```/tmp/mysysname.crt``` 23 | 24 | **Make sure to use the .crt extension. My certificate would not add unless I used the .crt file extension instead of .cer** 25 | 26 | Then I copied the ```mysysname.crt``` file to the ```/usr/local/share/ca-certificates``` directory. I suppose you could just save your cert there during export as well to save a step. 27 | Ex file copy: ```cp /tmp/mysysname.crt /usr/local/share/ca-certificates/mysysname.crt``` 28 | 29 | The last step is to register the new cert file using the following command line: 30 | ```sudo update-ca-certificates``` 31 | 32 | You should see a result similar to this indicating your certificate was added: 33 | ``` 34 | Updating certificates in /etc/ssl/certs... 35 | rehash: warning: skipping ca-certificates.crt,it does not contain exactly one certificate or CRL 36 | 1 added, 0 removed; done. 37 | Running hooks in /etc/ca-certificates/update.d... 38 | ``` 39 | 40 | Now if you run ```cwbping mysysname /ssl:1``` you should no longer see any errors if your SSL certificates are working as expected with the IBM i Access ODBC Driver. 41 | And you should now be able to create ODBC data sources or DSN-less connections that use connection strings and they should all work fine with SSL as well. 42 | 43 | If this didn't solve your issue, then you probably have something different happening in your environment. 44 | 45 | ## Links 46 | ibm-iaccess for Linux ODBC Configuration 47 | https://www.ibm.com/support/pages/ibm-iaccess-linux-odbc-configuration 48 | -------------------------------------------------------------------------------- /ibmi_acs_odbcssl_mac_issue.md: -------------------------------------------------------------------------------- 1 | # How to set up IBM i Access ODBC Driver for MacOS to use an SSL Certificate 2 | ```This article is not a full tutorial on setting up SSL on your IBM i. It covers the issue I had after SSL was set up and ODBC still was giving the CWBCO1050 certificate not trusted error on MacOS - M1.``` 3 | 4 | Installing and using the ```IBM i Access Client Solutions``` Java based software (which provides 5250, File Transfer IFS, Run SQL utilities, etc) and the MacOS ODBC driver which is installed with the ```ACS Mac App Pkg``` is usually a pretty easy process. 5 | 6 | There are two separate installers for: ```IBM i Access Client Solutions``` and ```ACS Mac App Pkg``` available from the following download site if you have an IBM login: 7 | https://www.ibm.com/support/pages/ibm-i-access-client-solutions 8 | 9 | After installation and configuration you can usually configure a Telnet session with Access Client Solutions or create and use an ODBC data source without issues. 10 | 11 | ***Until you want to use SSL to connect to your database via ODBC instead of unsecured access......*** 12 | 13 | I was trying to set up my IBM i Access ODBC Driver with SSL on a Mac M1 machine and every time I ran: 14 | ```cwbping mysysname /ssl:1``` to test SSL connectivity for the ODBC driver I got the following error: ```Error message CWBCO1050 - "The system certificate is not trusted".``` I got the same errors from the isql utility if I defined an ODBC data source with the ```SSL=1``` setting. Ex isql command to connect: ```isql -v mysysname user1 pass1``` 15 | 16 | My regular IBM i Access services (Java) such as Telnet were working fine with SSL, so I knew the issue had to be with the Mac based ODBC drivers (different technology - C/C++) and its need to use a different certificate store for SSL certs. Apparently since unixodbc is installed by HomeBrew (a package manager for MacOS), there is a related certificate store that needs to be used for trusted certificates instead of the Mac Keychain. The certificate store directory path used by HomeBrew is named: ```$HOMEBREW_PREFIX/etc/openssl@3/certs```. On my Mac ```$HOMEBREW_PREFIX``` is an environment variable that maps to directory: ```/opt/homebrew```. This expands the path to be: ```/opt/homebrew/etc/openssl@3/certs``` 17 | 18 | If you want to get an idea of where HomeBrew maps to on your system, open a terminal window and type: ```env``` and press Enter to list your environment variables. 19 | Example env list if you have any ```HOMEBREW_``` prefixed environment settings: 20 | ``` 21 | HOMEBREW_PREFIX=/opt/homebrew 22 | HOMEBREW_CELLAR=/opt/homebrew/Cellar 23 | HOMEBREW_REPOSITORY=/opt/homebrew 24 | ``` 25 | 26 | If you don't see any ```$HOMEBREW_``` prefixed environment variables in the env list, type: ```which brew``` and it should list the path to the ```brew``` executable. Ex: ```which brew``` on my system shows ```/opt/homebrew/bin/brew``` so the main path to HomeBrew is: ```/opt/homebrew```. 27 | 28 | Once you've determined where your openssl@3 directory is located it's time to export your certificate authority. 29 | 30 | Using the ```Key Management``` option from IBM i Access Client Solutions, I exported the trusted certificate file I wanted HomeBrew to trust and saved it to a file. In this example we'll say we exported it to file: ```/tmp/mysysname.cer``` 31 | 32 | Then I copied the ```mysysname.cer``` file to the ```/opt/homebrew/etc/openssl@3/certs``` directory. I suppose you could just save your cert there during export as well to save a step. 33 | Ex: ```cp /tmp/mysysname.cer /opt/homebrew/etc/openssl@3/certs/mysysname.cer``` 34 | 35 | The last step is to register the new cert file using the following command line: 36 | **These steps may work without using sudo since HomeBrew may not require sudo. I used sudo.** 37 | ```sudo $HOMEBREW_PREFIX/opt/openssl@3/bin/c_rehash``` 38 | -or- 39 | ```sudo /opt/homebrew/opt/openssl@3/bin/c_rehash``` (or whatever path you determined for your version of HomeBrew) 40 | 41 | 42 | Now if you run ```cwbping mysysname /ssl:1``` you should no longer see any errors if your SSL certificates are working as expected with the IBM i Access ODBC Driver. 43 | 44 | And you should now be able to create ODBC data sources or DSN-less connections that use connection strings and they should all work fine with SSL as well. 45 | 46 | If this didn't solve your issue, then you probably have something different happening in your environment. 47 | 48 | ## Another location I've found HomeBrew 49 | On my other Macbook I believe I'm using the Rosetta version of HomeBrew, so the locations for my cert files are: 50 | ```/usr/local/etc/openssl@3``` 51 | 52 | And the path for c_rehash is: 53 | ```/usr/local/bin/c_rehash``` 54 | 55 | 56 | ## Related links where I learned this: 57 | https://formulae.brew.sh/formula/openssl@3 58 | -------------------------------------------------------------------------------- /ibmi_acs_odbcssl_windows_issue_.md: -------------------------------------------------------------------------------- 1 | # How to set up IBM i Access ODBC Driver for Windows to use an SSL Certificate 2 | ```This article is not a full tutorial on setting up SSL on your IBM i. It covers the issue I had after SSL was set up and ODBC still was giving the CWBCO1050 certificate not trusted error.``` 3 | 4 | Installing and using the ```IBM i Access Client Solutions``` Java based software (which provides 5250, File Transfer IFS, Run SQL utilities, etc) and the Windows ODBC driver which is installed with the ```ACS Windows App Pkg English (64bit)``` is usually a pretty easy process. 5 | 6 | There are two separate installers for: ```IBM i Access Client Solutions``` and ```ACS Windows App Pkg English (64bit)``` available from the following download site if you have an IBM login: 7 | https://www.ibm.com/support/pages/ibm-i-access-client-solutions 8 | 9 | After installation and configuration you can usually configure a Telnet session with Access Client Solutions or create and use an ODBC data source without issues. 10 | 11 | ***Until you want to use SSL to connect to your database via ODBC instead of unsecured access......*** 12 | 13 | I was trying to set up my IBM i Access ODBC Driver with SSL on a Windows machine and every time I ran ```cwbping mysysname /ssl:1``` to test SSL connectivity for the ODBC driver I got the following error: ```Error message CWBCO1050 - "The system certificate is not trusted.``` 14 | 15 | My regular IBM i Access services (Java) such as Telnet were working fine with SSL, so I knew the issue had to be with the Windows based ODBC drivers (different technology - C/C++) and its need to use a different certificate store for SSL certs. The certificate store file for IBM i Access Windows package is named: ```C:\Users\Public\Documents\IBM\Client Access\cwbssldf.kdb``` and I believe it uses GSKit to encrypt and decrypt certificates. 16 | 17 | The ```CWBCO1050``` error usually occurs when you have SSL configured, but have not downloaded the public Certificate Authority certificate or the system Client/Server certificate to the PC key database. Or you have the public Certificate Authority certificate certificate downloaded but it's not marked marked as trusted in the PC key database." 18 | 19 | So initially I went through the instructions on the site listed below to make sure my certs were getting downloaded and placed into the IBM i Access Windows package key store file named: ```C:\Users\Public\Documents\IBM\Client Access\cwbssldf.kdb``` 20 | https://www.ibm.com/support/pages/importing-certificates-use-ibm-i-access-client-solutions-windows-application-package-acs-winap 21 | 22 | Downloading and installing the certs to the PC seemed to be working fine. 23 | 24 | Then I ran ```cwbping mysysname /ssl:1``` and kept getting: CWBCO1050 - "The system certificate is not trusted.``` 25 | 26 | Frustrating...... 27 | 28 | ## How to finally solve this issue 29 | After several hours of playing around with this, in the end it's actually pretty easy if you have the right little bits of information: You need to make sure all the certs you have added to the IBM i Access Windows package key store file named: ```C:\Users\Public\Documents\IBM\Client Access\cwbssldf.kdb``` are marked as ```Trusted```. 30 | 31 | Let's look at a little example: 32 | First open a DOS terminal window and run the following commands: 33 | 34 | Set the path to the gsk8capicmd.exe which is used to list or make changes to the ```cwbssldf.kdb``` key store file. This change will only be in place while the DOS Window is open. 35 | ```set PATH=C:\Program Files (x86)\IBM\gsk8\bin;C:\Program Files (x86)\IBM\gsk8\lib;%PATH%``` 36 | 37 | This command lists all the certs for IBM i Access for Windows key store (different than the Java keystore used by IBM i Access Client Solutions) 38 | ```gsk8capicmd.exe -cert -list all -db "C:\Users\Public\Documents\IBM\Client Access\cwbssldf.kdb" -pw ca400``` 39 | 40 | Your results may likely look similar to below: All trusted entries are prefixed with an exclamation point ```!``` 41 | Also In my scenario Godaddy is the provider for my wildcard domain certificate, but that shouldn't matter. 42 | In this list the bottom 5 entries are marked as untrusted due to the lack of the exclamation point. 43 | So we need to mark those last 5 entries as trusted. 44 | ```You may have more or less entries marked as untrusted``` 45 | ``` 46 | ! "RSA Secure Server Certification Authority" 47 | ! "VeriSign Class 3 Secure Server CA" 48 | ! "Entrust.net Certification Authority (2048)" 49 | ! "Entrust.net Client Certification Authority" 50 | ! "Entrust.net Global Client Certification Authority" 51 | ! "Entrust.net Global Secure Server Certification Authority" 52 | ! "Entrust.net Secure Server Certification Authority" 53 | ! "Entrust.net Certification Authority (2048) 29" 54 | ! "Entrust Root Certification Authority - EC1" 55 | ! "Entrust Root Certification Authority - EV" 56 | ! "Entrust Root Certification Authority - G2" 57 | ! "Thawte Personal Basic CA" 58 | ! "Thawte Personal Freemail CA" 59 | ! "Thawte Personal Premium CA" 60 | ! "Thawte Premium Server CA" 61 | ! "Thawte Server CA" 62 | ! "Thawte Primary Root CA - G2 ECC" 63 | ! "Thawte Primary Root CA" 64 | ! "VeriSign Class 1 Public Primary Certification Authority" 65 | ! "VeriSign Class 1 Public Primary Certification Authority - G2" 66 | ! "VeriSign Class 1 Public Primary Certification Authority - G3" 67 | ! "VeriSign Class 2 Public Primary Certification Authority" 68 | ! "VeriSign Class 2 Public Primary Certification Authority - G2" 69 | ! "VeriSign Class 2 Public Primary Certification Authority - G3" 70 | ! "VeriSign Class 3 Public Primary Certification Authority" 71 | ! "VeriSign Class 3 Public Primary Certification Authority - G2" 72 | ! "VeriSign Class 3 Public Primary Certification Authority - G3" 73 | ! "VeriSign Class 3 Public Primary Certification Authority - G5" 74 | ! "VeriSign Class 4 Public Primary Certification Authority - G2" 75 | ! "VeriSign Class 4 Public Primary Certification Authority - G3" 76 | "MYSYS.MYDDMAIN.COM - Tuesday, November 21, 2023 13:36:07" 77 | "acs_import_RS_71806731094500 CA - Tuesday, November 21, 2023 15:04:36" 78 | "acs_import_*.mydomain.com_71806234456600 CA - Tuesday, November 21, 2023 15:04:35" 79 | "acs_import_Go Daddy Secure Certificate Authority - G2_71806484262100 CA - Tuesday, November 21, 2023 15:04:35" 80 | "acs_import_Go Daddy Root Certificate Authority - G2_71806571558600 CA - Tuesday, November 21, 2023 15:04:35" 81 | ``` 82 | 83 | ## Marking key entries as trusted 84 | Using our example above, the following 5 commands can be run from the DOS Window to mark our 5 untrusted entries as trusted: 85 | ``` 86 | gsk8capicmd.exe -cert -modify -trust enable -label "MYSYS.MYDOMAIN.COM - Tuesday, November 21, 2023 13:36:07" -db "C:\Users\Public\Documents\IBM\Client Access\cwbssldf.kdb" -pw ca400 87 | gsk8capicmd.exe -cert -modify -trust enable -label "acs_import_RS_71806731094500 CA - Tuesday, November 21, 2023 15:04:36" -db "C:\Users\Public\Documents\IBM\Client Access\cwbssldf.kdb" -pw ca400 88 | gsk8capicmd.exe -cert -modify -trust enable -label "acs_import_*.mydomain.com_71806234456600 CA - Tuesday, November 21, 2023 15:04:35" -db "C:\Users\Public\Documents\IBM\Client Access\cwbssldf.kdb" -pw ca400 89 | gsk8capicmd.exe -cert -modify -trust enable -label "acs_import_Go Daddy Secure Certificate Authority - G2_71806484262100 CA - Tuesday, November 21, 2023 15:04:35" -db "C:\Users\Public\Documents\IBM\Client Access\cwbssldf.kdb" -pw ca400 90 | gsk8capicmd.exe -cert -modify -trust enable -label "acs_import_Go Daddy Root Certificate Authority - G2_71806571558600 CA - Tuesday, November 21, 2023 15:04:35" -db "C:\Users\Public\Documents\IBM\Client Access\cwbssldf.kdb" -pw ca400 91 | ``` 92 | 93 | Now if we repeat the ```-list``` command to see if all of our entries are now trusted, we can see they all have exclamation points ```!``` next to them which means all entries are trusted in the key file 94 | 95 | This command lists all the certs for IBM i Access for Windows key store (different than the Java keystore used by IBM i Access Client Solutions) 96 | ```gsk8capicmd.exe -cert -list all -db "C:\Users\Public\Documents\IBM\Client Access\cwbssldf.kdb" -pw ca400``` 97 | 98 | All entries in the cwbssldf.kdb cert file are now trusted. 99 | ``` 100 | ! "RSA Secure Server Certification Authority" 101 | ! "VeriSign Class 3 Secure Server CA" 102 | ! "Entrust.net Certification Authority (2048)" 103 | ! "Entrust.net Client Certification Authority" 104 | ! "Entrust.net Global Client Certification Authority" 105 | ! "Entrust.net Global Secure Server Certification Authority" 106 | ! "Entrust.net Secure Server Certification Authority" 107 | ! "Entrust.net Certification Authority (2048) 29" 108 | ! "Entrust Root Certification Authority - EC1" 109 | ! "Entrust Root Certification Authority - EV" 110 | ! "Entrust Root Certification Authority - G2" 111 | ! "Thawte Personal Basic CA" 112 | ! "Thawte Personal Freemail CA" 113 | ! "Thawte Personal Premium CA" 114 | ! "Thawte Premium Server CA" 115 | ! "Thawte Server CA" 116 | ! "Thawte Primary Root CA - G2 ECC" 117 | ! "Thawte Primary Root CA" 118 | ! "VeriSign Class 1 Public Primary Certification Authority" 119 | ! "VeriSign Class 1 Public Primary Certification Authority - G2" 120 | ! "VeriSign Class 1 Public Primary Certification Authority - G3" 121 | ! "VeriSign Class 2 Public Primary Certification Authority" 122 | ! "VeriSign Class 2 Public Primary Certification Authority - G2" 123 | ! "VeriSign Class 2 Public Primary Certification Authority - G3" 124 | ! "VeriSign Class 3 Public Primary Certification Authority" 125 | ! "VeriSign Class 3 Public Primary Certification Authority - G2" 126 | ! "VeriSign Class 3 Public Primary Certification Authority - G3" 127 | ! "VeriSign Class 3 Public Primary Certification Authority - G5" 128 | ! "VeriSign Class 4 Public Primary Certification Authority - G2" 129 | ! "VeriSign Class 4 Public Primary Certification Authority - G3" 130 | ! "MYSYS.MYDDMAIN.COM - Tuesday, November 21, 2023 13:36:07" 131 | ! "acs_import_RS_71806731094500 CA - Tuesday, November 21, 2023 15:04:36" 132 | ! "acs_import_*.mydomain.com_71806234456600 CA - Tuesday, November 21, 2023 15:04:35" 133 | ! "acs_import_Go Daddy Secure Certificate Authority - G2_71806484262100 CA - Tuesday, November 21, 2023 15:04:35" 134 | ! "acs_import_Go Daddy Root Certificate Authority - G2_71806571558600 CA - Tuesday, November 21, 2023 15:04:35" 135 | ``` 136 | 137 | Now if you run ```cwbping mysysname /ssl:1``` you should no longer see any errors if your SSL certificates are working as expected with the IBM i Access ODBC Driver. 138 | 139 | And you should now be able to create ODBC data sources or DSN-less connections that use connection strings and they should all work fine with SSL as well. 140 | 141 | If this didn't solve your issue, then you probably have something different happening in your environment. 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /ibmi_afp_overlays_pagesegments.md: -------------------------------------------------------------------------------- 1 | # Creating IBM i AFP Overlays or Page Segments 2 | The following links may be useful if you have to create an IBM i AFP Overlay or Page Segment 3 | 4 | ## Creating AFP Resources Using the AFP Printer Drivers 5 | https://www.ibm.com/support/pages/creating-afp-resources-using-afp-printer-drivers 6 | 7 | ## Ricoh Infoprint Manager -Installing and Configuring AFP Driver 8 | https://help.ricohsoftware.com/swinfocenter/infoprint-manager/en-US/IPM_Windows_project.ditamap/$/iprzc_pfd 9 | 10 | ## Midrange Wiki - Creating Overlays and Page Segments 11 | https://wiki.midrange.com/index.php/Creating_Overlays_and_Page_Segments 12 | 13 | ## AFP Driver - Creating a Page Segment 14 | https://afpdriver.com/AFPUserGuide/index.html?creating_a_page_segment.htm 15 | 16 | ## Ricoh - FREE AFP Viewer 17 | https://resources.ricohsoftware.com/cta/afp-viewer 18 | -------------------------------------------------------------------------------- /ibmi_default_profile_settings.md: -------------------------------------------------------------------------------- 1 | # Set up default QSH/PASE/Bash Profile Settings for IBM i Users 2 | In order to find open source packages from the command line in QShell, PASE or Bash without qualifying the path to ```/QOpenSys/pkgs/bin``` you should have the following profile files created in you your home directory on IBM i. 3 | 4 | ``` 5 | If you're doing any work with the IBM Open Source Packages you really want to make sure to set up your 6 | profile files to make life a little easier. 7 | ``` 8 | 9 | ``` 10 | .profile - QShell default settings for path info during login or STRQSH. 11 | 12 | .bash_profile - Bash default profile for path info during login. 13 | 14 | .bashrc - Bach default profile for path info if new bash session started. 15 | ``` 16 | 17 | ** If you want to skip the steps below and simplify the process of creating SSH/Bash/QShell profile files for your IBM i users, you should install the QShell on i library (QSHONI) https://www.github.com/richardschoen/qshoni and use the ```QSHSETPROF``` CL command in the ```QSHONI``` library to make life easy when creating user profile files. Just run QSHSETPROF with the appropriate user name and it creates all the files automatically for you. ** 18 | 19 | 20 | ## Listed below are sample file contents you can use to create your own default profiles 21 | 22 | ### Make sure your IBM i user has a HOME directory 23 | Run the following command from an SSH terminal to make sure your user has a home directory. Or create from 5250 via the MKDIR command. 24 | 25 | Our examples use ```USERID``` as a sample user name. You should use your own user profile. 26 | 27 | ```mkdir /home/USERID``` 28 | 29 | It may say the directory already exists or the dir will get created. Either is fine. 30 | 31 | ### Create .profile file 32 | Create the file in your ```/home/USERID``` directory. (Where USERID is your user profile) 33 | 34 | File name will be: ```/home/USERID/.profile``` 35 | 36 | From SSH terminal you can create an empty file via the following: 37 | ``` 38 | touch /home/USERID/.profile 39 | ``` 40 | Then you can edit from 5250 via EDTF command or using the nano or vi editors in SSH terminal 41 | 42 | ```nano /home/USERID/.profile``` 43 | 44 | Add the following date to the .profile file: 45 | ``` 46 | PATH=/QOpenSys/pkgs/bin:/QOpenSys/usr/bin:/usr/ccs/bin:/QOpenSys/usr/bin/X11:/usr/sbin:.:/usr/bin:$PATH 47 | ``` 48 | If using the nano editor, after adding the line to the file you can press ```Control-X```, then press ```Y``` to save the file and press enter again once the file name is displayed. The editor will exit. 49 | 50 | Let's see the file contents by typing the following command: 51 | ``` 52 | cat /home/USERID/.profile 53 | ``` 54 | You should see the path echoed to the SSH terminal: 55 | ``` 56 | PATH=/QOpenSys/pkgs/bin:/QOpenSys/usr/bin:/usr/ccs/bin:/QOpenSys/usr/bin/X11:/usr/sbin:.:/usr/bin:$PATH 57 | ``` 58 | 59 | Now if you do a ```STRQSH``` command from the IBM i, after the shell starts you should be able to type: ```git``` or any other open source command and press Enter and the command line parameters should be shown letting you know that it found the command in the search path. You can type any open source command line option that exists in ```/QOpenSys/pkgs/bin``` and it should work now without qualifying the directory path. 60 | 61 | ### Create .bashrc file 62 | Create the file in your ```/home/USERID``` directory. (Where USERID is your user profile) 63 | 64 | File name will be: ```/home/USERID/.bashrc``` 65 | 66 | From SSH terminal you can create an empty file via the following: 67 | ``` 68 | touch /home/USERID/.bashrc 69 | ``` 70 | Then you can edit from 5250 via EDTF command or using the nano or vi editors in SSH terminal 71 | 72 | ```nano /home/USERID/.bashrc``` 73 | 74 | Add the following data to the .bashrc file: 75 | ``` 76 | # Set bash path 77 | export PATH=/QOpenSys/pkgs/bin:/QOpenSys/pkg/lib:$PATH 78 | ``` 79 | If using the nano editor, after adding the line to the file you can press ```Control-X```, then press ```Y``` to save the file and press enter again once the file name is displayed. The editor will exit. 80 | 81 | Let's see the file contents by typing the following command: 82 | ``` 83 | cat /home/USERID/.bashrc 84 | ``` 85 | You should see the file data echoed to the SSH terminal. 86 | 87 | **Create the .bash_profile file before attempting to test if ```.bashrc``` works.** 88 | 89 | ### Create .bash_profile file 90 | Create the file in your ```/home/USERID``` directory. (Where USERID is your user profile) 91 | 92 | File name will be: ```/home/USERID/.bash_profile``` 93 | 94 | From SSH terminal you can create an empty file via the following: 95 | ``` 96 | touch /home/USERID/.bash_profile 97 | ``` 98 | Then you can edit from 5250 via EDTF command or using the nano or vi editors in SSH terminal 99 | 100 | ```nano /home/USERID/.bash_profile``` 101 | 102 | Add the following data to the .bash_profile file: 103 | ``` 104 | export PATH=/QOpenSys/pkgs/bin:/QOpenSys/pkg/lib:$PATH 105 | # Always execute the .bashrc script when logging in with bash as 106 | # default profile which will execute .base_profile upon login. 107 | # If default shell is QSH, .bashrc will execute when user calls 108 | # the bash command. 109 | # This keeps all actual path logic in the .bashrc file. 110 | # non-shell user 111 | if [ -f ~/.bashrc ]; then 112 | . ~/.bashrc 113 | fi 114 | ``` 115 | If using the nano editor, after adding the line to the file you can press ```Control-X```, then press ```Y``` to save the file and press enter again once the file name is displayed. The editor will exit. 116 | 117 | Let's see the file contents by typing the following command: 118 | ``` 119 | cat /home/USERID/.bash_profile 120 | ``` 121 | You should see the file data echoed to the SSH terminal. 122 | 123 | Now if you start a NEW bash or logout and back in if bash is you default shell, all commands in directory ```/QOpenSys/pkgs/bin``` should be available to you. 124 | -------------------------------------------------------------------------------- /ibmi_install_amazon_cli_v1.md: -------------------------------------------------------------------------------- 1 | # Installing and Using Amazon CLI on IBM i for S3 File/Object Management 2 | The Amazon command line interface (CLI) allows IBM i developers to interact with their Amazon services from the IBM i PASE command line.. 3 | 4 | Probably the most common use for the Amazon CLI might be to upload and download file objects from S3 storage buckets for use with IBM i. 5 | 6 | Also there are other cloud providers now providing S3 cloud compatible storage so you're not limited to Amazon as your cloud S3 provider. 7 | 8 | I took inspiration for this how-to from Diego Kesselman's article on LinkedIn to create this how-to. 9 | 10 | # Potential use cases 11 | Here are a few potential use cases for S3 storage and the Amazon CLI: 12 | 13 | Saving libraries or IFS files to save files and uploading to Amazon S3 storage. 14 | 15 | Downloading and restoring a library or IFS files from a save file stored on Amazon S3 storage. 16 | 17 | Uploading daily reports and other files to shared Amazon directories. (Similar to SharePoint). 18 | 19 | Uploading files to S3 storage so a trading partner can retrieve them. 20 | 21 | Upload working files from mobile devices to be picked up later by IBM i. 22 | 23 | Downloading files from S3 storage uploaded by a trading partner. 24 | 25 | # Amazon CLI Usage Links 26 | Link to Diego Kesselman's Linked in Article (inspiration for this page) 27 | https://www.linkedin.com/pulse/ibm-i-having-fun-cloud-object-storage-cos-diego-kesselman 28 | 29 | Amazon CLI V1 Documentation (There is a V2 API, but V1 is what is supported via Python3 currently) 30 | https://docs.aws.amazon.com/cli/latest/reference/s3/ls.html 31 | 32 | # Installing on IBM i 33 | 34 | ## Pre-requisite 35 | OS level should be IBM i V7R3 or above. 36 | 37 | Make sure all ```Python 3``` options are installed by the '``Open Source Package Management``` menu option in ACS. 38 | 39 | Log in to an IBM i SSH terminal session and make sure bash is the current shell. 40 | 41 | ## Install the Amazon CLI in PASE 42 | Run following command from SSH terminal. 43 | ```pip3 install awscli``` 44 | 45 | ## Set up your Amazon Credentials 46 | Run following command from SSH terminal. 47 | ```aws configure``` 48 | 49 | You will be prompted for your ```aws_access_key``` and ```aws_secret_access_key``` and region info as well. I only entered my access key and secret access key. 50 | 51 | The settings get saved in the following file for each user under their HOME directory: 52 | ```~/.aws/credentials``` 53 | 54 | ## Lets list our Amazon S3 Buckets 55 | Play around with the following aws list CLI commands. 56 | 57 | ```aws s3 ls``` will display a list of all your available buckets at the command line. 58 | ``` 59 | 2015-11-04 16:48:52 mybucket1 60 | 2016-01-02 11:39:04 mybucket2 61 | ``` 62 | 63 | ```aws s3 ls s3://mybucket1/``` will list all files and directories in mybucket1. Mine shows the following subdirectories. They may show ```PRE``` on the fornt of the list entries for a directory. 64 | ``` 65 | PRE dir1/ 66 | PRE dir2/ 67 | ``` 68 | 69 | ```aws s3 ls s3://mybucket1/dir1/``` will list all files and directories in mybucket1 under the dir1 directory. 70 | ``` 71 | 2023-08-27 08:32:33 155232 BACKUPIFS-20230827.zip 72 | 2023-08-28 14:31:26 155232 BACKUPIFS-20230828.zip 73 | ``` 74 | ## Let's download a file from our Amazon S3 bucket to the IFS 75 | The following example aws CLI commands can be used to download files from an S3 bucket to an IFS directory. 76 | 77 | ```aws s3 cp s3://mybucket1/dir1/BACKUPIFS-20230827.zip /tmp/BACKUPIFS-20230827.zip``` will download the ZIP backup file from S3 mybucket1/dir1 folder to the /tmp folder on our IFS. 78 | 79 | Successful download response: 80 | ```download: s3://mybucket//dir1/BACKUPIFS-20230827.zip to ../../../tmp/BACKUPIFS-20230827.zip``` 81 | 82 | ```aws s3 cp s3://mybucket1/dir1/BACKUPIFS-20230830.zip /tmp/BACKUPIFS-20230830.zip``` will try to download the non-existent backup ZIP file from S3 mybucket1/dir1 to the /tmp folder on our IFS but will fail because no file is found on S3 with this name. 83 | 84 | Error download response when file not found: 85 | ```fatal error: An error occurred (404) when calling the HeadObject operation: Key "dir1/BACKUPIFS-20230830.zip" does not exist``` 86 | 87 | ## Let's upload an IFS file to our Amazon S3 bucket 88 | The following example aws CLI commands can be used to upload files to an S3 bucket from an IFS directory. 89 | 90 | ```aws s3 cp /tmp/BACKUPIFS-20230827.zip s3://mybucket1/dir1/BACKUPIFS-20230827.zip``` will upload the selected ZIP file from the /tmp IFS directory to S3 mybucket1/dir1. 91 | 92 | Successful upload response: 93 | ```upload: ../../../tmp/BACKUPIFS-20230827.zip to s3://mybucket//dir1/BACKUPIFS-20230827.zip``` 94 | 95 | ```aws s3 cp /tmp/BACKUPIFS-20230827.zip s3://mybucket1/dir3/BACKUPIFS-20230827.zip``` will upload the selected ZIP file from the /tmp IFS directory to S3 mybucket1/dir3. (If dir3 does not exist in the bucket it will get automatically created.) 96 | 97 | Successful upload response: 98 | ```upload: ../../../tmp/BACKUPIFS-20230827.zip to s3://mybucket//dir3/BACKUPIFS-20230827.zip``` 99 | 100 | ```aws s3 cp /tmp/BACKUPIFS-20230827.zip s3://mybucket111/dir1/BACKUPIFS-20230827.zip``` will error while uploading the selected ZIP file from the /tmp IFS directory to S3 mybucket111/dir. (Bucket mybucket111 does not exist.) 101 | 102 | Error upload response when bucket not found: 103 | ``` 104 | upload failed: ../../../tmp/BACKUPIFS-20230827.zip to s3://mybucket111/dir1/BACKUPIFS-20230827.zip 105 | An error occurred (NoSuchBucket) when calling the PutObject operation: The specified bucket does not exist 106 | ``` 107 | ## More to come 108 | As I play more with the Amazon CLI I will update this article. There are lots of potential uses for the aws CLI command from IBM i. 109 | 110 | Feel free to send your updates to me for adding to the article by doing a pull request or creating an issue. 111 | 112 | ## Watch Out For 113 | As I was testing I found out that as of 8/28/2023, it appears that the version of the ```botocore``` framework used by ```awscli``` is a bit different than the version that is used by the ```s3fs``` Package I've used for other Python Amazon S3 processes. 114 | 115 | As of 8/28/2023 116 | ```awscli``` uses the following botocore version: botocore==1.31.36 with Python 3.9 on IBM i 117 | ```s3fs``` uses the following botocore version: botocore==1.27.59 with Python 3.9 on IBM i 118 | 119 | Because of thie you may want to create a separate virtual environment for the ```awscli``` if you're also using something like s3fs. 120 | 121 | ## Quickly create a virtual environment for awscli 122 | We will make a virtual environmnet for the aws cli in IFS directory ```/awsclivenv``` 123 | 124 | Create the environment without system packages (Recommended for a clean Python environment) 125 | ``` 126 | cd / 127 | python3 -m venv awsclienv 128 | ``` 129 | 130 | If you want an environment with a copy of your system packages. 131 | ``` 132 | cd / 133 | python3 -m venv awsclienv --system-site-packages 134 | ``` 135 | 136 | Activate the environment 137 | ```source /awsclivenv/bin/activate``` 138 | 139 | List your pip packages installed after activation. 140 | ```pip3 list ``` 141 | 142 | Install Amazon aws cli or other needed pip packages in the virtual environment (venv) 143 | ```pip3 install awscli``` 144 | 145 | Run any aws cli commands after environment has been activated. 146 | 147 | Deactivate environment when done 148 | ```deactivate``` 149 | 150 | Single command line to activate and run AWS dir list command 151 | ```source /awsclivenv/bin/activate;aws s3 ls s3://mybucket1/;deactivate``` 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /ibmi_mount_nfs_share.md: -------------------------------------------------------------------------------- 1 | # IBM i NFS Share Mount How-To Notes 2 | 3 | ## Overview 4 | Mounting an NFS share over an IFS directory is a great way to provide access to remote Windows or Linux file directories from IBM i and QShell/PASE without exposing them via NetServer, SMB and QTNC which can cause issues when user authentication doesn't match across systems. 5 | 6 | ❗ You should limit access to your NFS shares to the IBM i IP address so this adds another level of security by limiting which machines can access the NFS shares. This is done on your remote Windows or Linux NFS share configuration. 7 | 8 | ❗ You SHOULD NOT need to start the IBM i NFS Server in order to mount an IFS directory over an NFS file share. 9 | 10 | **Feel free to contribute any notes you have on accessing NFS file shares from IBM i.** 11 | 12 | ## NFS Share Network Mount Example 13 | For our example we will assume we have a remote Windows or Linux Server on IP address: 1.1.1.1 with a remote NFS share of /nfsmount1 that will get mounted over an IFS directory named /nfsmount1 for consistency. 14 | 15 | It's always a good idea to name your remote Windows and Linux directories, NFS shares and IFS directories consistently so the names are easily recognizable by your applications and users. 16 | 17 | #### Mount NFS Share using NFS share named /nfsmount1 over IFS directory /nfsmount1 18 | An NFS share is always mounted over an existing IFS directory path which means once mounted the local IFS files in the directory cannot be seen because the IFS directory is mapped to a remote NFS share and the local files in the IFS folder are hidden because of the mount. Once unmounted, the local files in teh IFS directory can be accessed again. 19 | 20 | ❗ Note: Usually if mounting an NFS share over an IFS directory, it's probably a good idea to dedicate the IFS directory just for the the NFS mount and don't put any files in the local IFS directory. This will help avoid confusion that may occur where users may think local files have disappeared. 21 | 22 | #### Create the IFS directory you will mount your NFS share over 23 | ```MKDIR DIR('/nfsmount1') DTAAUT(*RWX) OBJAUT(*ALL)``` 24 | 25 | #### This example mounts to an NFS share on remote NFS server: 1.1.1.1 on share /nfsmount1 26 | ``` 27 | MOUNT TYPE(*NFS) MFS('1.1.1.1:/nfsmount1') + 28 | MNTOVRDIR('/nfsmount1') + 29 | OPTIONS('rw,nosuid,retry=5,rsize=8096,wsize=8096,+ 30 | timeo=20,retrans=2,acregmin=30,acregmax=60,+ 31 | acdirmin=30,acdirmax=60,soft') + 32 | CODEPAGE(*BINARY *ASCII) 33 | ``` 34 | 35 | #### This example unmounts the NFS share that us mounted over IFS directory /nfsmount1 36 | ```UNMOUNT TYPE(*NFS) MNTOVRDIR('/nfsmount1') ``` 37 | 38 | #### How to see if an NFS share is mounted 39 | ```WRKLNK '/nfsmount1/*'``` 40 | 41 | If you can see files, the share is mounted. 42 | 43 | #### Another way to check NFS mount status. 44 | ```WRKLNK '/nfsmount1'``` 45 | 46 | ```Take option 8``` and you will see the following on the Display Attributes Screen if the remote NFS share is mounted: 47 | 48 | ``` 49 | Object . . . . . . : /nfsmount1 50 | 51 | Type . . . . . . . . . . . . . . . . . : DIR 52 | 53 | Owner . . . . . . . . . . . . . . . . : *NOUSRPRF 54 | System object is on . . . . . . . . . : Remote 55 | Object overflowed . . . . . . . . . : No 56 | 57 | Coded character set ID . . . . . . . . : 437 58 | Hidden file . . . . . . . . . . . . . : No 59 | PC system file . . . . . . . . . . . . : No 60 | Read only . . . . . . . . . . . . . . : No 61 | 62 | Need to archive (PC) . . . . . . . . . : No 63 | Need to archive (System) . . . . . . . : No 64 | ``` 65 | 66 | #### In this example the IFS directory doesn't have anything mounted over it 67 | ``` 68 | Object . . . . . . : /nfsmount1 69 | 70 | Type . . . . . . . . . . . . . . . . . : DIR 71 | 72 | Owner . . . . . . . . . . . . . . . . : RICHARD 73 | System object is on . . . . . . . . . : Local 74 | Auxiliary storage pool . . . . . . . . : 1 75 | Object overflowed . . . . . . . . . : No 76 | 77 | Coded character set ID . . . . . . . . : 37 78 | Hidden file . . . . . . . . . . . . . : No 79 | PC system file . . . . . . . . . . . . : No 80 | Read only . . . . . . . . . . . . . . : No 81 | ``` 82 | 83 | 84 | ## Copying Files from and to NFS Shares using the CPY CL Command 85 | 86 | #### Copy file from IFS to NFS location. Make sure to specify CCSID(437) and AUT(*INDIR) or you may get an authority error when copying files to an nfs directory from the IFS. 87 | ```CPY OBJ('/tmp/test.pdf') TOOBJ('/nfsmount1/test.pdf') TOCCSID(437) DTAFMT(*BINARY) REPLACE(*YES) AUT(*INDIR)``` 88 | 89 | #### Copy file from NFS to IFS location. Make sure to specify CCSID(437) and AUT(*INDIR) or you may get an authority error when copying files from an nfs directory to the IFS. 90 | ```CPY OBJ('/nfsmount1/test.pdf') TOOBJ('/tmp/test.pdf') FROMCCSID(437) DTAFMT(*BINARY) REPLACE(*YES) AUT(*INDIR)``` 91 | 92 | ## QShell/PASE IFS File Copy from and to NFS Shares 93 | 94 | Copying files is pretty much like copying any other file in QSH/PASE. Use the ```cp``` command. 95 | 96 | #### Initial copy from IFS to NFS mount if file doesn't exist on remote NFS share. If you do a WRKLNK option 8 on the file after copied, you will see a CCSID of 437. This can cause issues if you need to later replace the file on the remote NFS mount because the IBMi thinks it has a CCSID of 437. 97 | ```cp /tmp/test.pdf /nfsmount1/test.pdf``` 98 | 99 | #### Attempt to copy to NFS mount if file exists already. You may receive the following error because it appears the cp command is not CCSID aware. 100 | ``` 101 | cp /tmp/test.pdf /nfsmount1/test.pdf 102 | cp: 001-2230 Error found setting CCSID to 437 for file /nfsmount1/test3.pdf. 103 | Operation not supported.$ 104 | ``` 105 | 106 | #### Attempt to copy file to NFS mount if file exists already. The following options should work. Either use the -t switch option or first delete the remote NFS file with rm command. Then copy it as a new file via cp command and this should work. 107 | 108 | #### Copy file to NFS share and replace with -t switch 109 | ```cp -t /tmp/test.pdf /nfsmount1/test.pdf ``` 110 | 111 | I'm not exactly sure why the -t switch works to replace the remote file since it's exact usage documantation says: 112 | ``` 113 | -t, --target-directory=DIRECTORY 114 | copy all SOURCE arguments into DIRECTORY 115 | ``` 116 | Without the -t switch we get an error similar to the following: 117 | 118 | ``` 119 | cp: 001-2230 Error found setting CCSID to 437 for file /nfsmount1/test.pdf. Operation not supported. 120 | ``` 121 | 122 | If the -t switch works for you, that's good. Otherwise you can always remove ```rm``` the remote file before copying it with ```cp```. The fun of QShell/PASE. 123 | 124 | #### Remove existing file and copy to NFS share 125 | 126 | ``` 127 | rm /nfsmount1/test.pdf 128 | cp /tmp/test.pdf /nfsmount1/test.pdf 129 | ``` 130 | 131 | ## General Setup for NFS File Sharing from Windows or Linux 132 | 133 | #### Sharing Windows Files via NFS 134 | Install Windows Service for Unix on Windows 2012 135 | https://www.serverlab.ca/tutorials/windows/storage-file-systems/configuring-an-nfs-server-on-windows-server-2012-r2/ 136 | 137 | Install NFS Server on Windows 2019 138 | https://computingforgeeks.com/install-and-configure-nfs-server-on-windows-server 139 | 140 | #### Sharing NFS Directory from Windows 141 | 142 | Directory to share on C: drive 143 | ![image](https://user-images.githubusercontent.com/9791508/236639390-40151a89-5c1c-422c-b2ee-3bb23e99f503.png) 144 | 145 | Add Everyone user to the directory with permissions 146 | ![image](https://user-images.githubusercontent.com/9791508/236639457-fa2e7774-c153-47fc-b0d0-079df9009a39.png) 147 | 148 | Right click directory and go to the NFS Sharing Tab. 149 | 150 | Set the settings as shown. 151 | 152 | ![image](https://user-images.githubusercontent.com/9791508/236639534-32cab28a-f9c6-47c0-935f-9ef2ec7a9ce5.png) 153 | 154 | ![image](https://user-images.githubusercontent.com/9791508/236639572-87547451-53c4-4196-afe7-9642fdd86a40.png) 155 | 156 | Click Permissions tab to provide No Access, Read Only or Read-Write permissions to a remote system. 157 | 158 | In this example we explicitly set No Permissions for all machines and then add read/write permissions to the IBM i on IP address 192.168.101.21 159 | ![image](https://user-images.githubusercontent.com/9791508/236639704-a944b5ad-bba7-4d97-98f7-cf23c5057d7d.png) 160 | 161 | ![image](https://user-images.githubusercontent.com/9791508/236639713-5bb243ae-5bc8-424c-b563-5fb470293b97.png) 162 | 163 | ## Allow unmapped user access via NFS for IBMi when accessing Windows NFS shares 164 | 165 | You may need to do this on Windows 2016, 2019 and newer versions of Windows Server. 166 | 167 | Put ```Everyone``` user on the Windows directory and NFS share if possible. 168 | 169 | Add the ```Everyone``` user to ```NTFS permissions``` and give it ```Read/Write or Full Control```. 170 | 171 | Then check ```Allow unmapped user access by UID/GID```. 172 | 173 | Theoretically that should be what you need to do to make it work. 174 | 175 | Then from PASE try copying a file with the ```cp``` command to test as noted above. 176 | 177 | If that works, try copying files from a 5250 session via the ```CPY``` command as noted above. 178 | 179 | Now you don't need QNTC or SAMBA then at all for sending and receiving files from/to Windows shares. 180 | 181 | Example NFS permissions screen for Windows 2016, 2019 and above. 182 | 183 | ![image](https://user-images.githubusercontent.com/9791508/236643431-f5cf657a-ab57-4b41-bc0b-f12f70f0d896.png) 184 | 185 | #### Sharing Linux Files via NFS 186 | https://cloud.netapp.com/blog/azure-anf-blg-linux-nfs-server-how-to-set-up-server-and-client 187 | 188 | #### Additional IBM i NFS and Other NFS Links 189 | IBM i Network FIle System 190 | https://www.ibm.com/docs/en/i/7.5?topic=systems-network-file-system-nfs 191 | 192 | Windows Services for Network File Systems 193 | https://forsenergy.com/en-us/nfs__lh/html/1f02f8b2-e653-4583-8391-84d3411badd1.htm 194 | 195 | Windows Services for NFS - Allow Root and Anonymous Access to Resources by NFS Clients 196 | https://forsenergy.com/en-us/nfs__lh/html/47b01fb7-a6f7-4be0-ae99-2fbda7974a8b.htm 197 | 198 | Windows - Deploy Network File System (NFS) 199 | https://learn.microsoft.com/en-us/windows-server/storage/nfs/deploy-nfs 200 | 201 | 202 | -------------------------------------------------------------------------------- /ibmi_set_default_shell.md: -------------------------------------------------------------------------------- 1 | # Set IBM i User's Default Shell to Bash or back to QShell 2 | Nowadays, the best way to do this is to using QSYS2.SET_PASE_SHELL_INFO() SQL procedure. 3 | 4 | ### From 5250 Launch STRSQL and switch to SQL mode (Shift-F1, Option 1, Naming convention-*SQL) 5 | 6 | ### Set current user's shell to bash 7 | ```CALL QSYS2.SET_PASE_SHELL_INFO('*CURRENT', '/QOpenSys/pkgs/bin/bash')``` 8 | 9 | ### Set a specific user's shell to bash 10 | (requires *SECADM special auth plus *USE and *OBJMGT to the user profile) 11 | ```CALL QSYS2.SET_PASE_SHELL_INFO('USERID', '/QOpenSys/pkgs/bin/bash')``` 12 | 13 | ### Set the default shell which is returned for users that do not have a shell set 14 | (requires *SECADM special auth plus *USE and *OBJMGT to QSYS) 15 | ```CALL QSYS2.SET_PASE_SHELL_INFO('*DEFAULT', '/QOpenSys/pkgs/bin/bash')``` 16 | 17 | ## In case you want to set Shell to Bourne SHell - IBM i default I believe 18 | When you selec bsh as your default shell, you will see a $ on the command line prompt when you connect with an SSH terminal 19 | 20 | ### Set current user's shell to Bourne Shell - bsh 21 | ```CALL QSYS2.SET_PASE_SHELL_INFO('*CURRENT', '/QOpenSys/usr/bin/bsh')``` 22 | 23 | ### Set a specific user's shell to qsh 24 | (requires *SECADM special auth plus *USE and *OBJMGT to the user profile) 25 | ```CALL QSYS2.SET_PASE_SHELL_INFO('USERID', '/QOpenSys/usr/bin/bsh')``` 26 | 27 | ## In case you want to set Shell to QShell - Not usually recommended 28 | When you selec qsh as your default shell, you will see an empty command line prompt when you connect with an SSH terminal 29 | 30 | ### Set current user's shell to qsh 31 | ```CALL QSYS2.SET_PASE_SHELL_INFO('*CURRENT', '/QOpenSys/usr/bin/qsh')``` 32 | 33 | ### Set a specific user's shell to qsh 34 | (requires *SECADM special auth plus *USE and *OBJMGT to the user profile) 35 | ```CALL QSYS2.SET_PASE_SHELL_INFO('USERID', '/QOpenSys/usr/bin/qsh')``` 36 | 37 | ## Links 38 | 39 | ### Changing the Default Shell for Inbound Secure Shell (SSH) Connections to the IBM i 40 | https://www.ibm.com/support/pages/changing-default-shell-inbound-secure-shell-ssh-connections-ibm-i 41 | -------------------------------------------------------------------------------- /ibmi_shells.md: -------------------------------------------------------------------------------- 1 | # List of IBM i Shells 2 | This is my brain dump on IBM i shells after poking around the IFS. 3 | 4 | I generally use bash nowadays as my main shell. 5 | 6 | ## CALL QP2TERM 7 | ```/QOpenSys/usr/bin/-sh ``` 8 | 9 | ## STRQSH - Start QShell 10 | ```/QSYS.LIB/QSHELL.LIB/QZSHSH.PGM``` 11 | 12 | ## sh - /usr/bin/sh 13 | ```/usr/bin/sh``` 14 | -points to- 15 | ```/QSYS.LIB/QSHELL.LIB/QZSHSH.PGM``` 16 | 17 | ## QShell - qsh - /usr/bin/qsh 18 | ```/usr/bin/qsh``` 19 | -points to- 20 | ```/QSYS.LIB/QSHELL.LIB/QZSHSH.PGM``` 21 | 22 | ## QShell - qsh - Run QShell commands from PASE 23 | ```/QOpenSys/usr/bin/qsh``` 24 | -points to- 25 | ```/QOpenSys/QIBM/ProdData/OS400/PASE/bin/qsh``` 26 | 27 | ## Korn Shell - sh - /QOpenSys/pkgs/bin/sh 28 | ```/QOpenSys/usr/bin/sh``` 29 | -points to- 30 | ```/QOpenSys/QIBM/ProdData/OS400/PASE/bin/ksh``` 31 | 32 | ## Korn Shell - ksh - /QOpenSys/pkgs/bin/ksh 33 | ```/QOpenSys/usr/bin/ksh ``` 34 | -points to- 35 | ```/QOpenSys/QIBM/ProdData/OS400/PASE/bin/ksh``` 36 | 37 | ## Bourne Shell - bsh - /QOpenSys/pkgs/bin/bsh 38 | ```/QOpenSys/usr/bin/bsh``` 39 | -points to- 40 | ```/QOpenSys/QIBM/ProdData/OS400/PASE/bin/bsh``` 41 | 42 | ## Bourne Again Shell - bash - /QOpenSys/pkgs/bin/bash 43 | ```/QOpenSys/pkgs/bin/bash``` 44 | 45 | ## Links 46 | V7R5 PASE 47 | https://www.ibm.com/docs/en/i/7.5?topic=i-pase-shells-utilities 48 | 49 | Settingd Bash as You Default Shell 50 | https://ibmi-oss-docs.readthedocs.io/en/latest/troubleshooting/SETTING_BASH.html 51 | 52 | Korn Shell AIX Info 53 | https://www.ibm.com/docs/en/aix/7.2?topic=k-ksh-command 54 | 55 | Bourne Shell AIX Info 56 | https://www.ibm.com/docs/en/aix/7.1?topic=shells-bourne-shell 57 | -------------------------------------------------------------------------------- /ibmigccgetstarted.md: -------------------------------------------------------------------------------- 1 | # Install and configure gcc on IBM i and create Hello World App 2 | 3 | If you ever wanted to get started learning gcc C for creating IBM i PASE apps in less than 5 minutes, then here you go. 4 | 5 | # Installing gcc 6 | Install gcc yum packages from IBM i ACS Open Source Package Management 7 | ``` 8 | Package list: 9 | gcc-aix 10 | gcc-cplusplus-aix 11 | gcc-cpp-aix 12 | ``` 13 | # Create and compile hello.c 14 | 15 | Open a SSH/bash terminal window and run the following commands to create the empty hello.c file 16 | ``` 17 | PATH=/QOpenSys/pkgs/bin:/QOpenSys/usr/sbin:/QOpenSys/usr/bin 18 | export PATH 19 | cd / 20 | mkdir gccsamples 21 | cd /gccsamples 22 | touch hello.c 23 | ``` 24 | 25 | From your favorite bash or IFS editor, create and edit the hello.c file in ***/gccsamples/hello.c*** and add the following code 26 | ``` 27 | #include 28 | int main(int argc, char *argv[]) 29 | { 30 | printf("Hello World\n"); 31 | } 32 | ``` 33 | 34 | Save the source member and compile the hello program with the following commands 35 | ``` 36 | cd /gccsamples 37 | gcc -o hello hello.c 38 | ``` 39 | 40 | Now run the program by typing the following 41 | ``` 42 | hello 43 | ``` 44 | 45 | You should see 46 | ``` 47 | Hello World 48 | ``` 49 | 50 | Congratulations you're on your way to learning gcc 51 | 52 | # Links 53 | 54 | gcc reference docs 55 | https://gcc.gnu.org/onlinedocs/ 56 | 57 | Let me know if you have a favorite gcc sample or documentation link. 58 | 59 | -------------------------------------------------------------------------------- /ibmiperl.md: -------------------------------------------------------------------------------- 1 | # IBM i Perl Links 2 | 3 | 4 | # Links 5 | https://wiki.midrange.com/index.php/Setup_Perl_and_Apache 6 | 7 | http://www.cpan.org/ports/os400/ 8 | 9 | https://www.itjungle.com/2016/10/17/tfh101716-story03/ 10 | 11 | https://www.ibm.com/developerworks/data/library/techarticle/dm-0512greenstein/index.html 12 | 13 | -------------------------------------------------------------------------------- /ibmisecuresshsetup.md: -------------------------------------------------------------------------------- 1 | # Links for Setting up IBM i SSH Server Securely 2 | 3 | ### Security Bulletin: OpenSSH for IBM i is vulnerable to a machine-in-the-middle attack due to a flaw in the SSH transport protocol. [CVE-2023-48795] 4 | https://www.ibm.com/support/pages/security-bulletin-openssh-ibm-i-vulnerable-machine-middle-attack-due-flaw-ssh-transport-protocol-cve-2023-48795 5 | 6 | ### How to configure and use SSH on IBM i 7 | https://www.seidengroup.com/how-to-configure-and-use-ssh-on-ibm-i 8 | 9 | ### Autostart SSH Daemon with TCP/IP 10 | https://www.ibm.com/support/pages/how-setup-ibm-i-ssh-daemon-autostart-tcpip 11 | 12 | ### Open Source and IBM i Security 13 | https://www.mcpressonline.com/security/ibm-i-os400-i5os/open-source-and-ibm-i-security 14 | 15 | ### Controlling Access to SSH on IBM i 16 | https://www.mcpressonline.com/security/ibm-i-os400-i5os/controlling-access-to-ssh-on-ibm-i 17 | 18 | ### Configuring the IBM i ssh, sftp, and scp clients to use public-key authentication 19 | https://www.ibm.com/support/pages/configuring-ibm-i-ssh-sftp-and-scp-clients-use-public-key-authentication 20 | 21 | ### 5 Actions for IBM i Administrators in the New Year 22 | https://www.mcpressonline.com/security/ibm-i-os400-i5os/5-actions-for-ibm-i-administrators-in-the-new-year 23 | 24 | ### Expert Tips for Setting Up Public Key Authentication on IBM i 25 | https://www.youtube.com/watch?v=FaXn-96K65U 26 | 27 | ### Setting up SSH Access to IBM i 28 | https://www.shieldadvanced.com/Blog/setting-up-ssh-access-to-ibm-i 29 | 30 | ### How to Set Up a SSH Banner on IBM i: A Professional Guide 31 | https://www.youtube.com/watch?v=p-7QsBd3UPQ 32 | 33 | ### SSH on the IBM i with BASH, PUTTY and WINSCP 34 | https://www.youtube.com/watch?v=OwkgpH0zm8Y 35 | 36 | ### Syslog Daemon 37 | https://www.ibm.com/support/pages/syslog-syslogd-pase-ibm-i 38 | 39 | ### SSHD can use Syslog 40 | https://www.ibm.com/support/pages/sshd-can-use-unix-syslog-facilities-logging 41 | 42 | ### IBM i OSS - Setup SSH and VS Code and Configure Bash 43 | https://www.youtube.com/watch?v=DxfM3MUPT9k 44 | 45 | ### Conquer the IBM i World with OpenSSH!! 46 | https://www.tug.ca/tec/Sessions/Handouts/PDF/23B-Conquer%20the%20IBM%20i%20World%20with%20OpenSSH.pdf 47 | -------------------------------------------------------------------------------- /ibmisqlsamples.md: -------------------------------------------------------------------------------- 1 | # IBM i SQL Samples 2 | 3 | ## Select all spool files matching a specific spool file name - Basic 4 | ``` 5 | SELECT * FROM QSYS2.OUTPUT_QUEUE_ENTRIES_BASIC WHERE 6 | SPOOLED_FILE_NAME like 'LABINV' 7 | ``` 8 | ## Select all spool files matching a specific spool file name - Extended 9 | ``` 10 | SELECT * FROM QSYS2.OUTPUT_QUEUE_ENTRIES WHERE 11 | SPOOLED_FILE_NAME like 'LABINV' 12 | ``` 13 | 14 | ## Select object statistics for a library 15 | ``` 16 | SELECT * FROM TABLE 17 | (QSYS2.OBJECT_STATISTICS('QGPL','ALL')) AS A 18 | ``` 19 | ## Select object statistics for a library 20 | ``` 21 | SELECT * FROM TABLE 22 | (QSYS2.OBJECT_STATISTICS('QGPL','ALL')) AS A 23 | ``` 24 | ## Select object statistics for all libraries 25 | ``` 26 | SELECT * FROM TABLE (QSYS2.OBJECT_STATISTICS('*ALL','ALL')) AS A 27 | ``` 28 | ## Select TCP info for current connection. Good for getting local PC/Server client IP 29 | ``` 30 | SELECT * FROM QSYS2.TCPIP_INFO 31 | ``` 32 | ## Netstat Connection Info 33 | ``` 34 | SELECT * FROM QSYS2.NETSTAT_INFO 35 | 36 | // This one is to list unsecured ports 37 | select * 38 | from qsys2.netstat_job_info 39 | where local_port not in 40 | (9470, 9471, 9472, 9473, 9474, 9475, 9476, 448, 2005, 2010, 5544, 5566, 5577, 992, 22, 9480, 942) 41 | and Local_Address <> ('127.0.0.1') 42 | and Local_Address not like ('::%') 43 | and Local_Address <> ('0.0.0.0') 44 | ``` 45 | ## Netstat Connection Info. Check for Local Port 22 active on IPV4 46 | ``` 47 | SELECT * FROM QSYS2.NETSTAT_INFO WHERE 48 | CONNECTION_TYPE = 'IPV4' and local_port=22 49 | ``` 50 | 51 | ## Select Active Jobs 52 | https://www.rpgpgm.com/2015/11/getting-active-jobs-data-using-sql.html 53 | https://www.rpgpgm.com/2019/07/extracting-jobs-name-from-job-name.html 54 | https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_72/rzajq/rzajqudfactivejobinfo.htm 55 | ``` 56 | // Select all jobs 57 | SELECT JOB_NAME,JOB_TYPE,JOB_STATUS,SUBSYSTEM, 58 | ELAPSED_CPU_PERCENTAGE AS PERCENT 59 | FROM TABLE(QSYS2.ACTIVE_JOB_INFO(JOB_NAME_FILTER => '*ALL')) A 60 | ORDER BY ELAPSED_CPU_PERCENTAGE DESC 61 | 62 | // Filtering by job status 63 | SELECT JOB_NAME,JOB_TYPE,JOB_STATUS,SUBSYSTEM 64 | FROM TABLE(QSYS2.ACTIVE_JOB_INFO()) B 65 | WHERE JOB_STATUS = 'MSGW' 66 | ORDER BY JOB_NAME 67 | 68 | // Filtering by job name 69 | SELECT JOB_NAME,JOB_TYPE,JOB_STATUS,SUBSYSTEM, 70 | CPU_TIME 71 | FROM TABLE(QSYS2.ACTIVE_JOB_INFO()) C 72 | WHERE JOB_NAME LIKE '%SIMON%' 73 | ORDER BY CPU_TIME DESC 74 | 75 | // Query and Parse Job Info and filter on 26 character JOB_NAME 76 | SELECT ORDINAL_POSITION AS ORD, 77 | SUBSTR(JOB_NAME, 78 | LOCATE_IN_STRING(JOB_NAME,'/',-1)+1) as JOBNAME, 79 | SUBSTR(JOB_NAME, 80 | LOCATE_IN_STRING(JOB_NAME,'/',1)+1, 81 | (LOCATE_IN_STRING(JOB_NAME,'/',-1)-1) 82 | - (LOCATE_IN_STRING(JOB_NAME,'/',1))) as JOBUSER, 83 | SUBSTR(JOB_NAME,1,6) as JOBNUMBER, 84 | JOB_TYPE as JOBTYPE,JOB_STATUS as JOBSTATUS, 85 | SUBSYSTEM 86 | FROM 87 | TABLE(QSYS2.ACTIVE_JOB_INFO(JOB_NAME_FILTER => '*ALL')) A 88 | where JOB_NAME LIKE '%%' 89 | ``` 90 | 91 | ## Select All Inquiry Messages from QSYSOPR Message Queue 92 | Great way to monitor for selected messages and then respond 93 | ``` 94 | SELECT MESSAGE_QUEUE_LIBRARY, MESSAGE_QUEUE_NAME, MESSAGE_ID, 95 | MESSAGE_TYPE, MESSAGE_SUBTYPE, 96 | CAST(MESSAGE_TEXT AS VARCHAR(1024)) MESSAGE_TEXT, SEVERITY, 97 | MESSAGE_TIMESTAMP, MESSAGE_KEY, ASSOCIATED_MESSAGE_KEY, FROM_USER, 98 | FROM_JOB, FROM_PROGRAM, MESSAGE_FILE_LIBRARY, MESSAGE_FILE_NAME, 99 | MESSAGE_TOKENS, 100 | CAST( MESSAGE_SECOND_LEVEL_TEXT as varchar(4096)) MESSAGE_SECOND_LEVEL_TEXT 101 | FROM QSYS2.MESSAGE_QUEUE_INFO WHERE MESSAGE_QUEUE_LIBRARY ='QSYS' and 102 | message_queue_name = 'QSYSOPR' and 103 | message_type = 'INQUIRY' 104 | ``` 105 | 106 | ## Select Active Job Info 107 | Great way to get info for active jos and subsystems they run in 108 | ``` 109 | SELECT * FROM TABLE(QSYS2.ACTIVE_JOB_INFO(SUBSYSTEM_LIST_FILTER => 'MONITOR')) A Or SELECT * FROM TABLE(QSYS2.ACTIVE_JOB_INFO(SUBSYSTEM_LIST_FILTER => 'QHTTPSVR')) A 110 | 111 | Obviously just change 'MONITOR' or QHTTPSVR to what is needed. 112 | 113 | select subsystem_description_library, subsystem_description, maximum_active_jobs, 114 | current_active_jobs, subsystem_monitor_job, text_description, 115 | controlling_subsystem, workload_group, signon_device_file_library, 116 | signon_device_file, secondary_language_library, iasp_name 117 | from qsys2.subsystem_info 118 | where status = 'ACTIVE' 119 | order by current_active_jobs desc; 120 | ``` 121 | 122 | ## Set default shell to bash 123 | Nowadays, the best way to do this is to using QSYS2.SET_PASE_SHELL_INFO() SQL procedure. 124 | 125 | ``` 126 | -- set current user's shell 127 | CALL QSYS2.SET_PASE_SHELL_INFO('*CURRENT', '/QOpenSys/pkgs/bin/bash'); 128 | 129 | -- set a specific user's shell 130 | -- (requires *SECADM special auth plus *USE and *OBJMGT to the user profile) 131 | CALL QSYS2.SET_PASE_SHELL_INFO('THATUSER', '/QOpenSys/pkgs/bin/bash'); 132 | 133 | -- set the default shell which is returned for users that do not have 134 | -- (requires *SECADM special auth plus *USE and *OBJMGT to QSYS) 135 | CALL QSYS2.SET_PASE_SHELL_INFO('*DEFAULT', '/QOpenSys/pkgs/bin/bash'); 136 | ``` 137 | https://stackoverflow.com/questions/23913957/set-default-pase-ibm-i-shell-for-individual-user 138 | 139 | ## Check if any users have default user password 140 | ``` 141 | select * from qsys2.user_info where user_default_password = 'YES' and previous_signon < current date - 60 days 142 | ``` 143 | ## Query IFS Directory /tmp 144 | From rpgpgm.com 145 | https://www.rpgpgm.com/2019/11/using-sql-to-list-directories-and-files.html 146 | ``` 147 | SELECT PATH_NAME,OBJECT_TYPE,CREATE_TIMESTAMP,LAST_USED_TIMESTAMP, 148 | DATA_SIZE FROM TABLE(QSYS2.IFS_OBJECT_STATISTICS('/tmp','YES')) 149 | ``` 150 | 151 | ## Query Source Member Info 152 | https://www.rpgpgm.com/2021/12/searching-for-member-information-with.html 153 | ``` 154 | SELECT SYSTEM_TABLE_SCHEMA AS "Library", 155 | SYSTEM_TABLE_NAME AS "File", 156 | TO_CHAR(COUNT(*),'999G999') AS "No. mbrs" 157 | FROM QSYS2.SYSPARTITIONSTAT 158 | WHERE SYSTEM_TABLE_SCHEMA = 'QSHONI' 159 | AND SOURCE_TYPE IS NOT NULL 160 | GROUP BY SYSTEM_TABLE_SCHEMA,SYSTEM_TABLE_NAME 161 | ORDER BY 1,2; 162 | 163 | SELECT SYSTEM_TABLE_SCHEMA AS "Library", 164 | SYSTEM_TABLE_NAME AS "File", 165 | SYSTEM_TABLE_MEMBER AS "Member", 166 | SOURCE_TYPE AS "Type", 167 | TO_CHAR(NUMBER_ROWS,'999G999G999G999') AS "Records", 168 | TO_CHAR(DATA_SIZE,'999G999G999G999') AS "Size", 169 | CREATE_TIMESTAMP AS "Created", 170 | LAST_SOURCE_UPDATE_TIMESTAMP AS "Last updated", 171 | PARTITION_TEXT AS "Member text" 172 | FROM QSYS2.SYSPARTITIONSTAT 173 | WHERE SYSTEM_TABLE_SCHEMA = 'QSHONI' 174 | AND SOURCE_TYPE IS NOT NULL 175 | ORDER BY 1,2,3; 176 | ``` 177 | 178 | ## Generate a 24 month list of dates 179 | ``` 180 | SELECT DATE(CURRENT_DATE - 365 DAYS + (LEVEL - 1) DAY) AS DateValue 181 | FROM SYSIBM.SYSDUMMY1 182 | CONNECT BY LEVEL <= 731; 183 | ``` 184 | 185 | -------------------------------------------------------------------------------- /ibmisqlserverfreetds.md: -------------------------------------------------------------------------------- 1 | # Connect to Microsoft SQL Server from IBM i Using ODBC and FreeTDS 2 | 3 | IBM i Open Source Developers can now connect directly to SQL Server using the FreeTDS Libraries and ODBC 4 | 5 | Overview from the FreeTDS site: http://www.freetds.org 6 | 7 | FreeTDS is a set of libraries for Unix and Linux that allows your programs to natively talk to Microsoft SQL Server and Sybase databases. 8 | 9 | Technically speaking, FreeTDS is an open source implementation of the TDS (Tabular Data Stream) protocol used by these databases for their own clients. It supports many different flavors of the protocol and three APIs to access it. Additionally FreeTDS works with other software such as Perl and PHP, providing access from those languages as well. 10 | 11 | **FreeTDS has many possible uses.** It has been used by Unix/Linux webservers to present data stored in SQL Server to the web, to port SQL Server database code from NT to Unix, to import data into SQL Server from a Unix source, and to provide database access on platforms (such as realtime systems) that have no native drivers. 12 | 13 | # IBM i Prerequisites for FreeTDS 14 | 15 | Make sure open source package Management is installed on IBM i via ACS 16 | 17 | Make sure all unixODBC yum packages installed on IBM i 18 | 19 | Install unixODBC packages 20 | ``` 21 | yum install unixODBC* 22 | 23 | -or individually- 24 | 25 | yum install unixODBC 26 | yum install unixODBC-devel 27 | ``` 28 | 29 | Make sure you have installed the FreeTDS yum packages 30 | 31 | Install FreeTDS packages 32 | ``` 33 | yum install freetds* 34 | 35 | -or individually- 36 | 37 | yum install freetds 38 | yum install freetds-devel 39 | yum install freetds-odbc 40 | ``` 41 | 42 | # Testing ODBC connectivity to SQL Server 43 | 44 | For this example we're configuring a SQL Server running on Port 1433 45 | 46 | From your favorite SSH editor (vi, nano, vscode, etc.) or a 5250 session Edit the ODBC.ini file and create a data source entry for your SQL Server. The save the file. 47 | 48 | File Name: ```/QOpenSys/etc/odbc.ini``` 49 | 50 | Ex CL command to edit from a 5250 session: 51 | 52 | ```edtf '/QOpenSys/etc/odbc.ini' ``` 53 | 54 | Sample entry for an SQL Server system: (Use IP address or host name) 55 | ``` 56 | [mysqlserver] 57 | Driver = FreeTDS 58 | Server = mysqlserver.com 59 | Port = 1433 60 | TDS_Version = 7.2 61 | ``` 62 | 63 | Trying out the connection with isql from a shell session command line 64 | ``` 65 | isql -v mysqlserver user password 66 | ``` 67 | 68 | If the connection works, you should see the isql commmand line and Connected!: 69 | ``` 70 | +---------------------------------------+ 71 | | Connected! | 72 | | | 73 | | sql-statement | 74 | | help [tablename] | 75 | | quit | 76 | | | 77 | +---------------------------------------+ 78 | SQL> 79 | ``` 80 | 81 | Let's do a test query where we have a database named: ```testdb``` and a table named: ```names```. SQL server also puts user tables in the default: ```dbo``` schema unless you have changed something on your SQL server. 82 | ``` 83 | select * from testdb.dbo.names 84 | ``` 85 | 86 | Results: 87 | ``` 88 | +------------+---------------------------------------------------+---------------------------------------------------+ 89 | | id | firstname | lastname | 90 | +------------+---------------------------------------------------+---------------------------------------------------+ 91 | | 1 | Robert | Johnston | 92 | | 2 | Maddy | Carbury | 93 | +------------+---------------------------------------------------+---------------------------------------------------+ 94 | SQLRowCount returns 2 95 | 2 rows fetched 96 | ``` 97 | 98 | **You should now be set to use the FreeTDS ODBC driver with your Python, Node, PHP or other apps. Enjoy** 99 | 100 | # DSN-less Connection String 101 | https://www.freetds.org/userguide/dsnless.html 102 | 103 | https://www.freetds.org/userguide/OdbcConnAttr.html 104 | ``` 105 | DRIVER=FreeTDS;SERVER=;PORT=1433;DATABASE=;TDS_Version=7.2;UID=;PWD=' 106 | ``` 107 | 108 | # DSN-less Connection String Samples 109 | ``` 110 | # Connect to mysqlserver.com database demodb on port 1433 111 | DRIVER=FreeTDS;SERVER=mysqlserver.com;PORT=1433;DATABASE=demodb;TDS_Version=7.2;UID=sa;PWD=mypassword' 112 | # Connect to SQL Server on TCP address: 1.1.1.1 database demodb on port 1433 113 | DRIVER=FreeTDS;SERVER=1.1.1.1;PORT=1433;DATABASE=demodb;TDS_Version=7.2;UID=sa;PWD=mypassword' 114 | ``` 115 | 116 | # Web Links on FreeTDS 117 | http://www.freetds.org 118 | 119 | https://stackoverflow.com/questions/33341510/how-to-install-freetds-in-linux 120 | 121 | Send me your favorite FreeTDS info links. 122 | -------------------------------------------------------------------------------- /ibmisshserverportconfig.md: -------------------------------------------------------------------------------- 1 | # Setting Up SSH Daemon on IBM i to Use Port Other Than 22 2 | 3 | Log on to a 5250 session on your IBM i system. 4 | 5 | Edit the SSH Daemon config file. 6 | 7 | The edit file command would look as follows: 8 | 9 | ``` 10 | edtf '/QOpenSys/QIBM/UserData/SC1/OpenSSH/etc/sshd_config' 11 | ``` 12 | 13 | Once the edit screen comes up it may look as follows: 14 | 15 | ``` 16 | # $OpenBSD: sshd_config,v 1.75 2007/03/19 01:01:29 djm Exp $ 17 | 18 | # This is the sshd server system-wide configuration file. See 19 | # sshd_config(5) for more information. 20 | 21 | # This sshd was compiled with PATH=/QOpenSys/usr/bin:/usr/ccs/bin:/QOpenSys 22 | 23 | # The strategy used for options in the default sshd_config shipped with 24 | # OpenSSH is to specify options with their default value where 25 | # possible, but leave them commented. Uncommented options change a 26 | # default value. 27 | 28 | Port 2022 29 | #Port22 30 | ``` 31 | Add a new entry for the new port. Ex: Port 2022 and comment (#) the old entry if not already commented. 32 | 33 | After adding the port entry for port 2022, you can press F3 to save and exit the config file editor. 34 | 35 | My preference is to put ports up in the 60000+ range. 36 | 37 | Stop and restart the SSH daemon with the following commands 38 | 39 | ``` 40 | ENDTCPSVR *SSHD 41 | 42 | Wait 10 seconds 43 | 44 | STRTCPSVR *SSHD 45 | ``` 46 | Run the following command to make sure port 2022 is active: 47 | 48 | ```NETSTAT OPTION(*CNN) ``` 49 | 50 | If you see local port 2022 is active then you should be able to log in to the SSH server on port 2022. 51 | 52 | ``` 53 | Remote Remote Local 54 | Opt Address Port Port Idle Time State 55 | * * as-admi > 100:11:23 Listen 56 | * * as-admi > 100:17:44 Listen 57 | * * as-admi > 100:17:44 Listen 58 | * * as-admi > 100:17:44 Listen 59 | 60 | * * 2022 000:06:12 Listen 61 | 62 | ``` 63 | 64 | You've completed the first step to securing your SSH server. 65 | 66 | You should now be able to connect to your IBM i using the selected SSH TCP/IP port. 67 | 68 | There are several OpenSSH server settings available, but the first step is getting SSH off of a non-standard port. 69 | 70 | -------------------------------------------------------------------------------- /ileastic-build-qshell.md: -------------------------------------------------------------------------------- 1 | # Instructions to successfully build ILEAstic from GitHub 2 | It appears there is an issue building the ILEAstic and NOXDB applications from the initial git close using an SSH terminal. 3 | 4 | However the build process does seem to work via a QShell terminal. Not sure wht but it works. 5 | 6 | The open project issue is: Install gmake issue #153 7 | https://github.com/sitemule/ILEastic/issues/153 8 | 9 | Site for ILEAstic 10 | https://github.com/sitemule/ILEastic 11 | 12 | ## The issue with building from an SSH terminal 13 | - Before trying to QSH install I tried building via a bash session via an SSH terminal. I made sure that the ```/QOpenSys/pkgs/bin``` open source packages were in my search path. However when I tried the build steps as listed on the readme.md page from SSH, the build failed based on same error as issue #53 above. 14 | 15 | - Based on the issue, what I learned from the #153 issue is that I could build the ILEASTIC and NOXDB app libraries from the green screen using the QShell terminal interface. 16 | ❗I'm not sure why this works from QShell and not SSH, but it does build. 17 | 18 | ## Clone and build steps from a 5250 session for building ILEASTIC 19 | - First review the readme.md on the ILEAstic site for build prerequisite requirements: https://github.com/sitemule/ILEastic 20 | 21 | - Sign on to a 5250 command line session with a user that has permissions to build code. 22 | 23 | - Set the multi-threaded env variable **before starting/entering the QShell terminal**. 24 | ``` 25 | ADDENVVAR ENVVAR('QIBM_MULTI_THREADED') VALUE('Y') CCSID(*JOB) LEVEL(*JOB) REPLACE(*YES) 26 | ``` 27 | 28 | - Start QShell terminal via ```STRQSH``` command. 29 | 30 | - Set your path with following export statement from within QSH terminal: 31 | ``` 32 | export PATH=/QOpenSys/pkgs/bin:$PATH 33 | ``` 34 | 35 | - Run the following commands from the QSH terminal to clone and build the project. Same steps as the ILEAstic site uses. 36 | ``` 37 | mkdir /prj 38 | cd /prj 39 | git -c http.sslVerify=false clone --recurse-submodules https://github.com/sitemule/ILEastic.git 40 | cd ILEastic 41 | gmake 42 | ``` 43 | 44 | - If all works as expected, the ILEASTIC library should exist with the following list of objects (```WRKOBJPDM ILEASTIC```): 45 | ``` 46 | BASE64 *PGM RPGLE ILEastic Example Server 47 | DATACHUNKS *PGM RPGLE ILEastic Example Server 48 | FASTCGI01 *PGM RPGLE ILEastic Example Server 49 | HEADER *PGM RPGLE ILEastic Example Server 50 | HELLOWORLD *PGM RPGLE ILEastic Example Server 51 | INVALIDREQ *PGM RPGLE ILEastic Example Server 52 | JSONDATA *PGM RPGLE ILEastic Example Server 53 | JSONP *PGM RPGLE ILEastic Example Server 54 | MULTROUTES *PGM RPGLE ILEastic Example Server 55 | NOXDBCUST *PGM RPGLE ILEastic Example Server 56 | PLUGIN *PGM RPGLE ILEastic Example Server 57 | QUERYSTR *PGM RPGLE ILEastic Example Server 58 | ROUTEID *PGM RPGLE ILEastic Example Server 59 | SCHEDULER *PGM RPGLE ILEastic Example Server 60 | STATICFILE *PGM RPGLE ILEastic Example Server 61 | ILEASTIC *SRVPGM CLE ILEastic - programable applicationserver for ILE 62 | ILEFASTCGI *SRVPGM CLE 63 | JSONXML *SRVPGM 64 | H *FILE PF-SRC 65 | QCLLESRC *FILE PF-SRC 66 | QRPGLEREF *FILE PF-SRC 67 | QSRVSRC *FILE PF-SRC 68 | ILEASTIC *BNDDIR 69 | JSONXML *BNDDIR 70 | NOXDB *BNDDIR 71 | ``` 72 | Now that the ILEASTIC library exists you are ready to start building HTTP server apps with ILEastic. 73 | 74 | Re-visit the site to continue: https://github.com/sitemule/ILEastic 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /install-python-ibmivirtual-environment.md: -------------------------------------------------------------------------------- 1 | # IBM i Example to Create a Python Virtual Environment in PASE 2 | 3 | # Make sure the IBM i environment is set up for Python development 4 | 5 | ### Install the Development Group Tools (gcc, git, cmake, tar etc.) 6 | ``` yum group install 'Development tools' ``` 7 | ``` yum install gcc10*``` 8 | ``` yum install gcc12*``` 9 | ### Install Unix ODBC Driver 10 | ``` yum install unixODBC ``` 11 | ``` yum install unixODBC-devel ``` 12 | ### Install IBM i Access ODBC Driver 13 | ``` yum install ibm-iaccess* ``` 14 | ### Install Python 3.6 and Python 3.9 Packages 15 | ``` yum install python3* ``` 16 | 17 | ### List installed Python base pip packages for Python 3.6 18 | Run following command to list base packages to see what pip packages are installed: **pip3.6 list** 19 | The list should look similar to the list below: 20 | ``` 21 | Package Version 22 | --------------- -------- 23 | asn1crypto 0.24.0 24 | bcrypt 3.1.4 25 | cffi 1.11.5 26 | cryptography 2.8 27 | ibm-db 2.0.5.12 28 | idna 2.8 29 | itoolkit 1.6.1 30 | Jinja2 2.11.2 31 | lxml 4.2.1 32 | MarkupSafe 1.1.1 33 | numpy 1.15.4 34 | pandas 0.22.0 35 | paramiko 2.6.0 36 | Pillow 5.0.0 37 | pip 21.1.2 38 | psutil 5.5.1 39 | psycopg2 2.8.5 40 | pycparser 2.19 41 | PyNaCl 1.2.1 42 | pyodbc 4.0.27 43 | python-dateutil 2.8.0 44 | pytz 2018.5 45 | PyYAML 5.3.1 46 | pyzmq 17.1.2 47 | scikit-learn 0.19.1 48 | scipy 1.1.0 49 | setuptools 57.0.0 50 | six 1.10.0 51 | wheel 0.36.2 52 | ``` 53 | 54 | ### List installed Python base pip packages for Python 3.9 55 | Run following command to list base packages to see what pip packages are installed: **pip3.9 list** 56 | The list should look similar to the list below: 57 | ``` 58 | Package Version 59 | --------------- -------- 60 | bcrypt 3.2.0 61 | beniget 0.4.1 62 | cffi 1.14.5 63 | cryptography 3.4.7 64 | Cython 0.29.24 65 | gast 0.5.3 66 | ibm-db 2.0.5.15 67 | itoolkit 1.7.0 68 | joblib 1.1.0 69 | lxml 4.6.3 70 | numpy 1.21.4 71 | pandas 1.3.4 72 | paramiko 2.7.2 73 | Pillow 8.3.1 74 | pip 21.1.2 75 | ply 3.11 76 | psutil 5.8.0 77 | psycopg2 2.9.1 78 | pybind11 2.8.1 79 | pycparser 2.20 80 | PyNaCl 1.4.0 81 | pyodbc 4.0.31 82 | python-dateutil 2.8.1 83 | pythran 0.10.0 84 | pytz 2021.1 85 | pyzmq 22.1.0 86 | scikit-learn 1.0.1 87 | scipy 1.7.3 88 | setuptools 57.0.0 89 | six 1.16.0 90 | threadpoolctl 3.0.0 91 | wheel 0.36.2 92 | ``` 93 | 94 | # Make Python virtual environment directory 95 | This example creates /pythonenv1 96 | ```mkdir /pythonenv1``` 97 | 98 | # Create a virtual environment 99 | 100 | ## Create virtual environment with site packages (Recommended) 101 | It's a good idea to install with the site packages for IBM i because your get all the base packages installed via yum. Plus you can still install specific Python pip package versions in the virtual environment (venv). 102 | ```python3 -m venv /pythonenv1 --system-site-packages --copies``` (Installs using default version of Python3.) 103 | ### You can also specifically set up the new virtual environment to use Python 3.6 or 3.9 104 | Use the appropriate python command variant if desired: 105 | ```python3.6 -m venv /pythonenv1 --system-site-packages --copies``` 106 | ```python3.9 -m venv /pythonenv1 --system-site-packages --copies``` 107 | 108 | :star: Creating a venv with site packages will include ibm-db and itoolkit which installs via the python3 based yum packages. 109 | :star: Any of these base packages should not be installed via pip as they are part of the Python yum RPMs. 110 | :star: pip should not be upgraded directly via pip as the support level of pip is part of the Python yum RPMs. 111 | 112 | 113 | ## Create virtual environment without site packages 114 | You can install your new virtual environment without site packages. You can still install other pip packages in the venv except for ibm-db, itoolkit and possibly the other packages that get installed as part of the Python yum site package installers. SO if you don't need any of the yum-based Python site packages, this method can be used if desired for a lighter weight virtual enviornment. 115 | ```python3 -m venv /pythonenv1``` (Installs using default version of Python3.) 116 | ```python3.6 -m venv /pythonenv1``` 117 | ```python3.9 -m venv /pythonenv1``` 118 | 119 | # Activate the Python environment 120 | ```source /pythonenv1/bin/activate``` 121 | 122 | # Command prompt looks like this after virtual environment (venv) activation 123 | ```(pythonenv1) -bash-5.1$``` 124 | 125 | # List installed Python packages globally or when a virtual environment is activated 126 | This command works in the base Python environment or an active virtual environment. 127 | ```pip3 list``` 128 | 129 | Example package list: 130 | ``` 131 | Package Version 132 | ---------- ------- 133 | pip 22.0.4 134 | setuptools 58.1.0 135 | ``` 136 | 137 | # Installing Python packages with pip - potential issues with V7R4 and V7R5 138 | 139 | ```Pre V7R4``` you can simply install with pip3 command. gcc is used which is gcc v6.x. 140 | ``` 141 | pip3 install pyodbc 142 | pip3 install flask 143 | pip3 install itoolkit 144 | pip3 install ibm-db 145 | ``` 146 | 147 | ```For V7R4 and V7R5``` - pip3 processes **MAY require** gcc10 compiler to build so use CC/GCC prefixes below for installing pip3 packages. Or set the CC and CXX environment variable before installing packages with pip3. 148 | ```CC='gcc-10 -pthread' CXX='g++-10 -pthread' pip3 install pyodbc``` 149 | ```CC='gcc-10 -pthread' CXX='g++-10 -pthread' pip3 install flask``` 150 | 151 | Or export CC and CXX as an environment variable and then run pip3 stuff. 152 | (Could also add the export of CC and CXX to your .bash_profile or .bashrc file) 153 | ```export CC='gcc-10 -pthread' CXX='g++-10 -pthread'``` 154 | 155 | After exporting the CC and CXX variables, install your pip3 packages 156 | ``` 157 | pip3 install pyodbc 158 | pip3 install flask 159 | ``` 160 | 161 | # Installing specific default pip packages in your active virtual environment 162 | Create a **requirements.txt** file in your **virtual environment directory** in a subdirectory called **src**. You could also place the requirements.txt in your desired app directory instead. it doesn't really matter as long as your virtual environment has been activated. Just don't put them in the root of the virtual environment directory. (Ex: /pythonenv1) 163 | 164 | Ex: ```/pythonenv1/src/requirements.txt``` 165 | 166 | Example **requirements.txt** file with one or more pip packages listed. This example just has **Flask** listed. You can find the various pip package versions available by going to the https://pypi.org site. 167 | ``` 168 | flask>=3.0.0 169 | #Install flask and associated requirements 170 | ``` 171 | 172 | Run the following command line to change to the requirements.txt directory and install the pip requirements for flask in your active virtual environment: 173 | 174 | ``` 175 | cd /pythonenv1/src 176 | pip3 install -r requirements.txt 177 | ``` 178 | This command line example will install flask and any specifically needed pre-requisites in the active virtual environment or globally if you happened to deactivate your virtual environment. 179 | 180 | # Run any python app script you want to test or run 181 | Run any of your scripts or additional pip3 installs needed in the environment once the environment has been activated. 182 | 183 | # Deactivate the active Python venv 184 | ```deactivate ``` 185 | 186 | # Misc - creating a custom gcc link for gcc10 187 | ``` 188 | mkdir mydir 189 | ln -s /QOpenSys/pkgs/bin/gcc-10 mydir/gcc 190 | ln -s /QOpenSys/pkgs/bin/g++-10 mydir/g++ 191 | PATH=$PWD/mydir:$PATH 192 | ``` 193 | :star: Note: You may want to create above links in ~/bin directory instead of mydir. I have not tried this but it was recommended as something to try. I think just setting the CC and CXX environment variables should work fine. 194 | 195 | # Misc - Running your Python script from a classic IBM i CL job or job scheduler 196 | This example runs a Python script named: **hello.py** from the /python directory using virtual environment **/pythonenv1** and the **QSHPYRUN** command which is part of the QShell on i utilities. https://github.com/richardschoen/qshoni The virtual enviornment is activated and then deactivated aftr the python script has run. 197 | ``` 198 | QSHONI/QSHPYRUN SCRIPTDIR('/python') 199 | SCRIPTFILE(hello.py) 200 | PYVERSION(3.9) 201 | VENVPATH('/pythonenv1') 202 | DSPSTDOUT(*YES) 203 | ``` 204 | 205 | # Misc - Same sequence as above to run script in a selected virtual environment via bash command line or bash script 206 | ``` 207 | source /pythonenv1/bin/activate 208 | python3 /python/hello.py 209 | deactivate 210 | 211 | ``` 212 | 213 | 214 | 215 | 216 | -------------------------------------------------------------------------------- /install-rsync-daemon-onibmi.md: -------------------------------------------------------------------------------- 1 | # Install and configure rsync daemon on IBM i 2 | 3 | rsync is a Unix/Linux based file syncronization tool. The rsync daemon allows rsync to run as a TCP server on port 873 or on any other custom TCP/IP port. 4 | rsync can also be used over samba or ssh file access, but this document focuses on the rsync daemon. 5 | There are a ton of configuration options available. This just focuses on simple examples to get you started. 6 | 7 | Install rsync yum packages from IBM i ACS Open Source Package Management 8 | ``` 9 | Package list: 10 | rsync - Current version: 3.2.3-1 11 | ``` 12 | Log in to SSH as an IBM i user 13 | 14 | If not started, start the bash shell by typing ***bash*** unless bash is already your default shell. 15 | 16 | Run the following shell command line sequence to set up the directories needed. If they already exist that's OK 17 | ``` 18 | mkdir /QOpenSys/var/run 19 | mkdir /QOpenSys/var/log 20 | 21 | Demo directories: 22 | 23 | mkdir /rsyncback1 24 | mkdir /rsyncback2 25 | 26 | ``` 27 | 28 | Make sure rsync is available in your search path or via its source path by typing the rsync command and pressing Enter. 29 | ``` 30 | rsync 31 | 32 | -or- 33 | 34 | /QopenSys/pkgs/bin/rsync 35 | ``` 36 | 37 | As a command response you should see something similar to the following: 38 | ``` 39 | rsync version 3.2.3 protocol version 31 40 | Copyright (C) 1996-2020 by Andrew Tridgell, Wayne Davison, and others. 41 | Web site: https://rsync.samba.org/ 42 | Capabilities: 43 | 64-bit files, 64-bit inums, 64-bit timestamps, 64-bit long ints, 44 | socketpairs, hardlinks, hardlink-specials, symlinks, no IPv6, atimes, 45 | batchfiles, inplace, append, no ACLs, no xattrs, optional protect-args, 46 | iconv, symtimes, no prealloc, stop-at, no crtimes 47 | Optimizations: 48 | no SIMD, no asm, openssl-crypto 49 | Checksum list: 50 | md5 md4 none 51 | Compress list: 52 | zstd zlibx zlib none 53 | 54 | rsync comes with ABSOLUTELY NO WARRANTY. This is free software, and you 55 | are welcome to redistribute it under certain conditions. See the GNU 56 | General Public Licence for details. 57 | 58 | rsync is a file transfer program capable of efficient remote update 59 | via a fast differencing algorithm. 60 | 61 | Usage: rsync [OPTION]... SRC [SRC]... DEST 62 | or rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST 63 | or rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST 64 | or rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/DEST 65 | or rsync [OPTION]... [USER@]HOST:SRC [DEST] 66 | or rsync [OPTION]... [USER@]HOST::SRC [DEST] 67 | or rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST] 68 | The ':' usages connect via remote shell, while '::' & 'rsync://' usages connect 69 | to an rsync daemon, and require SRC or DEST to start with a module name. 70 | 71 | Options 72 | --verbose, -v increase verbosity 73 | --info=FLAGS fine-grained informational verbosity 74 | --debug=FLAGS fine-grained debug verbosity 75 | --stderr=e|a|c change stderr output mode (default: errors) 76 | --quiet, -q suppress non-error messages 77 | --no-motd suppress daemon-mode MOTD 78 | --checksum, -c skip based on checksum, not mod-time & size 79 | --archive, -a archive mode; equals -rlptgoD (no -H,-A,-X) 80 | --no-OPTION turn off an implied OPTION (e.g. --no-D) 81 | --recursive, -r recurse into directories 82 | --relative, -R use relative path names 83 | --no-implied-dirs don't send implied dirs with --relative 84 | --backup, -b make backups (see --suffix & --backup-dir) 85 | --backup-dir=DIR make backups into hierarchy based in DIR 86 | --suffix=SUFFIX backup suffix (default ~ w/o --backup-dir) 87 | --update, -u skip files that are newer on the receiver 88 | --inplace update destination files in-place 89 | --append append data onto shorter files 90 | --append-verify --append w/old data in file checksum 91 | --dirs, -d transfer directories without recursing 92 | --mkpath create the destination's path component 93 | --links, -l copy symlinks as symlinks 94 | --copy-links, -L transform symlink into referent file/dir 95 | --copy-unsafe-links only "unsafe" symlinks are transformed 96 | --safe-links ignore symlinks that point outside the tree 97 | --munge-links munge symlinks to make them safe & unusable 98 | --copy-dirlinks, -k transform symlink to dir into referent dir 99 | --keep-dirlinks, -K treat symlinked dir on receiver as dir 100 | --hard-links, -H preserve hard links 101 | --perms, -p preserve permissions 102 | --executability, -E preserve executability 103 | --chmod=CHMOD affect file and/or directory permissions 104 | --acls, -A preserve ACLs (implies --perms) 105 | --xattrs, -X preserve extended attributes 106 | --owner, -o preserve owner (super-user only) 107 | --group, -g preserve group 108 | --devices preserve device files (super-user only) 109 | --specials preserve special files 110 | -D same as --devices --specials 111 | --times, -t preserve modification times 112 | --atimes, -U preserve access (use) times 113 | --open-noatime avoid changing the atime on opened files 114 | --crtimes, -N preserve create times (newness) 115 | --omit-dir-times, -O omit directories from --times 116 | --omit-link-times, -J omit symlinks from --times 117 | --super receiver attempts super-user activities 118 | --fake-super store/recover privileged attrs using xattrs 119 | --sparse, -S turn sequences of nulls into sparse blocks 120 | --preallocate allocate dest files before writing them 121 | --write-devices write to devices as files (implies --inplace) 122 | --dry-run, -n perform a trial run with no changes made 123 | --whole-file, -W copy files whole (w/o delta-xfer algorithm) 124 | --checksum-choice=STR choose the checksum algorithm (aka --cc) 125 | --one-file-system, -x don't cross filesystem boundaries 126 | --block-size=SIZE, -B force a fixed checksum block-size 127 | --rsh=COMMAND, -e specify the remote shell to use 128 | --rsync-path=PROGRAM specify the rsync to run on remote machine 129 | --existing skip creating new files on receiver 130 | --ignore-existing skip updating files that exist on receiver 131 | --remove-source-files sender removes synchronized files (non-dir) 132 | --del an alias for --delete-during 133 | --delete delete extraneous files from dest dirs 134 | --delete-before receiver deletes before xfer, not during 135 | --delete-during receiver deletes during the transfer 136 | --delete-delay find deletions during, delete after 137 | --delete-after receiver deletes after transfer, not during 138 | --delete-excluded also delete excluded files from dest dirs 139 | --ignore-missing-args ignore missing source args without error 140 | --delete-missing-args delete missing source args from destination 141 | --ignore-errors delete even if there are I/O errors 142 | --force force deletion of dirs even if not empty 143 | --max-delete=NUM don't delete more than NUM files 144 | --max-size=SIZE don't transfer any file larger than SIZE 145 | --min-size=SIZE don't transfer any file smaller than SIZE 146 | --max-alloc=SIZE change a limit relating to memory alloc 147 | --partial keep partially transferred files 148 | --partial-dir=DIR put a partially transferred file into DIR 149 | --delay-updates put all updated files into place at end 150 | --prune-empty-dirs, -m prune empty directory chains from file-list 151 | --numeric-ids don't map uid/gid values by user/group name 152 | --usermap=STRING custom username mapping 153 | --groupmap=STRING custom groupname mapping 154 | --chown=USER:GROUP simple username/groupname mapping 155 | --timeout=SECONDS set I/O timeout in seconds 156 | --contimeout=SECONDS set daemon connection timeout in seconds 157 | --ignore-times, -I don't skip files that match size and time 158 | --size-only skip files that match in size 159 | --modify-window=NUM, -@ set the accuracy for mod-time comparisons 160 | --temp-dir=DIR, -T create temporary files in directory DIR 161 | --fuzzy, -y find similar file for basis if no dest file 162 | --compare-dest=DIR also compare destination files relative to DIR 163 | --copy-dest=DIR ... and include copies of unchanged files 164 | --link-dest=DIR hardlink to files in DIR when unchanged 165 | --compress, -z compress file data during the transfer 166 | --compress-choice=STR choose the compression algorithm (aka --zc) 167 | --compress-level=NUM explicitly set compression level (aka --zl) 168 | --skip-compress=LIST skip compressing files with suffix in LIST 169 | --cvs-exclude, -C auto-ignore files in the same way CVS does 170 | --filter=RULE, -f add a file-filtering RULE 171 | -F same as --filter='dir-merge /.rsync-filter' 172 | repeated: --filter='- .rsync-filter' 173 | --exclude=PATTERN exclude files matching PATTERN 174 | --exclude-from=FILE read exclude patterns from FILE 175 | --include=PATTERN don't exclude files matching PATTERN 176 | --include-from=FILE read include patterns from FILE 177 | --files-from=FILE read list of source-file names from FILE 178 | --from0, -0 all *-from/filter files are delimited by 0s 179 | --protect-args, -s no space-splitting; wildcard chars only 180 | --copy-as=USER[:GROUP] specify user & optional group for the copy 181 | --address=ADDRESS bind address for outgoing socket to daemon 182 | --port=PORT specify double-colon alternate port number 183 | --sockopts=OPTIONS specify custom TCP options 184 | --blocking-io use blocking I/O for the remote shell 185 | --outbuf=N|L|B set out buffering to None, Line, or Block 186 | --stats give some file-transfer stats 187 | --8-bit-output, -8 leave high-bit chars unescaped in output 188 | --human-readable, -h output numbers in a human-readable format 189 | --progress show progress during transfer 190 | -P same as --partial --progress 191 | --itemize-changes, -i output a change-summary for all updates 192 | --remote-option=OPT, -M send OPTION to the remote side only 193 | --out-format=FORMAT output updates using the specified FORMAT 194 | --log-file=FILE log what we're doing to the specified FILE 195 | --log-file-format=FMT log updates using the specified FMT 196 | --password-file=FILE read daemon-access password from FILE 197 | --early-input=FILE use FILE for daemon's early exec input 198 | --list-only list the files instead of copying them 199 | --bwlimit=RATE limit socket I/O bandwidth 200 | --stop-after=MINS Stop rsync after MINS minutes have elapsed 201 | --stop-at=y-m-dTh:m Stop rsync at the specified point in time 202 | --write-batch=FILE write a batched update to FILE 203 | --only-write-batch=FILE like --write-batch but w/o updating dest 204 | --read-batch=FILE read a batched update from FILE 205 | --protocol=NUM force an older protocol version to be used 206 | --iconv=CONVERT_SPEC request charset conversion of filenames 207 | --checksum-seed=NUM set block/file checksum seed (advanced) 208 | --ipv4, -4 prefer IPv4 209 | --ipv6, -6 prefer IPv6 210 | --version, -V print the version + other info and exit 211 | --help, -h (*) show this help (* -h is help only on its own) 212 | 213 | Use "rsync --daemon --help" to see the daemon-mode command-line options. 214 | Please see the rsync(1) and rsyncd.conf(5) man pages for full documentation. 215 | See https://rsync.samba.org/ for updates, bug reports, and answers 216 | rsync error: syntax or usage error (code 1) at main.c(1732) [client=3.2.3] 217 | ``` 218 | 219 | ``` 220 | TODO: 221 | /etc/rsyncd.config 222 | rsyncd.secrets for passwords 223 | rsync command line to send/receive files with and without security 224 | port restrictions 225 | helpful links 226 | ``` 227 | 228 | ## Set up sample **/etc/rsync.conf** file with NO security for initial test. Uncomment secrets file to enable security. 229 | 230 | ``` 231 | lock file = /QOpenSys/var/run/rsync.lock 232 | log file = /QOpenSys/var/log/rsyncd.log 233 | pid file = /QOpenSys/var/run/rsyncd.pid 234 | 235 | [rsyncback1] 236 | path = /rsyncback1 237 | comment = Rsync backup directory 1 238 | read only = no 239 | list = yes 240 | uid = 0 241 | ##gid = 0 242 | read only = no 243 | list = yes 244 | # If auth users disabled, no password required 245 | auth users = rsyncclient 246 | secrets file = /etc/rsyncd.secrets 247 | 248 | [rsyncback2] 249 | path = /rsyncback2 250 | comment = Rsync backup directory 1 251 | read only = no 252 | list = yes 253 | uid = 0 254 | ##gid = 0 255 | read only = no 256 | list = yes 257 | # If auth users disabled, no password required 258 | auth users = rsyncclient 259 | secrets file = /etc/rsyncd.secrets 260 | ``` 261 | 262 | ## Set up sample **/etc/rsync.secrets** file to hold user/password combinations 263 | 264 | ``` 265 | rsyncclient=password1 266 | sysop1=password2 267 | sysop3=password3 268 | ``` 269 | ## rsync PASE/QSH daemon startup 270 | 271 | ``` 272 | rsync --deamon 273 | ``` 274 | 275 | ## Viewing active rsync deamon server job 276 | From a 5250 session, run "NETSTAT *CNN" to verify the rsync daemon server is listening on port 873. You should see an entry for Local Port 873 which tells you the server is listening for connections. Use ```option 5 and then press F8``` to see active jobs for the rsync daemon. 277 | ``` 278 | -------------------------------------------------------------------------------- 279 | Work with IPv4 Connection Status 280 | System: SYS1 281 | Type options, press Enter. 282 | 3=Enable debug 4=End 5=Display details 6=Disable debug 283 | 8=Display jobs 284 | 285 | Remote Remote Local 286 | Opt Address Port Port Idle Time State 287 | * * 873 000:05:22 Listen 288 | -------------------------------------------------------------------------------- 289 | ``` 290 | 291 | Active rsync daemon servr job 292 | 293 | ``` 294 | Display Jobs Using Connection 295 | System: SYS1 296 | Connection type . . . . . . : *TCP 297 | Local address . . . . . . . : * 298 | Local port . . . . . . . . . : 873 299 | Remote address . . . . . . . : * 300 | Remote port . . . . . . . . : * 301 | 302 | Type options, press Enter. 303 | 5=Work with job 304 | 305 | Current 306 | Opt Name User Number Type User 307 | QP0ZSPWP QSECOFR 495329 *BCH RICHARD 308 | 309 | 310 | 311 | 312 | 313 | 314 | Bottom 315 | F3=Exit F5=Refresh F6=Print F9=Command line F12=Cancel 316 | ``` 317 | 318 | 319 | 320 | 321 | ## rsync PASE/QSH daemon ending 322 | 323 | ``` 324 | kill -QUIT $( cat /QOpenSys/var/run/rsyncd.pid ) 325 | rm /QOpenSys/var/run/rsyncd.pid 326 | **Removing the pid file is optional as it will get overwritten on next startup 327 | ``` 328 | ## Send a file on the same system (localhost) as a test using rsync daemon 329 | 330 | First create a file named ```/tmp/test.txt ``` or some other file with data in it. 331 | 332 | Instructions and sample command list: 333 | 334 | Export the password for user: rsyncclient to an environment variable. The rsync daemon users the RSYNC_PASSWORD environment variable. 335 | 336 | Run the rsync command. After it runs, the synced **test.txt** file should exist in file: **/rsyncback1/test.txt** 337 | 338 | After running the rsync command , cleanup the RSYNC_PASSWORD environment variable. 339 | 340 | **Note: If you comment out the **auth users** section in your **rsyncd.config** file with a #, then no security is used by the rsync daemon. Therefore no password is required. However you open your system up to security exposure. Minimally you should maybe limit which host IP addresses can access the IBM i on ```TCP/IP port 873``` 341 | 342 | ``` 343 | export RSYNC_PASSWORD=password1 344 | rsync -avz /tmp/test.txt rsync://rsyncclient@localhost/rsyncback1 345 | export RSYNC_PASSWORD= 346 | ``` 347 | ## Receive a file on the same system (localhost) as a test using rsync daemon 348 | 349 | Instructions and sample command list: 350 | 351 | Export the password for user: rsyncclient to an environment variable. The rsync daemon users the RSYNC_PASSWORD environment variable. 352 | 353 | Run the rsync command. After it runs, the synced **test.txt** file should exist in file: **/tmp/temp-receive.txt** 354 | 355 | After running the rsync command , cleanup the RSYNC_PASSWORD environment variable. 356 | 357 | **Note: If you comment out the **auth users** section in your **rsyncd.config** file with a #, then no security is used by the rsync daemon. Therefore no password is required. However you open your system up to security exposure. Minimally you should maybe limit which host IP addresses can access the IBM i on ```TCP/IP port 873``` 358 | 359 | ``` 360 | export RSYNC_PASSWORD=password1 361 | rsync -avz rsync://rsyncclient@localhost/rsyncback1/test.txt /tmp/test-receive.txt 362 | export RSYNC_PASSWORD= 363 | ``` 364 | 365 | ## Continue learning rsync 366 | 367 | Now refer to standard rsync documentation or links below as needed for additional daemon or rsync command line options. 368 | 369 | Feel free to contribute links or other helpful tips. 370 | 371 | # Links 372 | 373 | Rsync web site 374 | https://rsync.samba.org 375 | 376 | rsync - Linux man page 377 | https://linux.die.net/man/1/rsync 378 | -------------------------------------------------------------------------------- /installcronie.md: -------------------------------------------------------------------------------- 1 | # Install and configure Cron Scheduling on IBM i 2 | 3 | From IBM: Now available for #IBMi: cron, via the 'cronie' RPM package! Anacron, too! 4 | 5 | This package can be a good way to schedule your open source jobs or CL commands to run on a regular basis. 6 | 7 | Install cronie yum packages from IBM i ACS Open Source Package Management 8 | ``` 9 | Package list: 10 | cronie 11 | cronie-anacron 12 | ``` 13 | # Setting up sample crontab system schedule file 14 | 15 | From your favorite bash editor, edit the system crontab file: in ***/QOpenSys/etc/crontab*** 16 | 17 | **The example listed below sends a message to QSYSOPR via calling an IBMi CL Command** 18 | ``` 19 | SHELL=/QOpenSys/pkgs/bin/bash 20 | PATH=/QOpenSys/pkgs/bin:/QOpenSys/usr/sbin:/QOpenSys/usr/bin 21 | MAILTO=qsecofr 22 | 23 | # For details see man 4 crontabs 24 | 25 | # Example of job definition: 26 | # .---------------- minute (0 - 59) 27 | # | .------------- hour (0 - 23) 28 | # | | .---------- day of month (1 - 31) 29 | # | | | .------- month (1 - 12) OR jan,feb,mar,apr ... 30 | # | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat 31 | # | | | | | 32 | # * * * * * ibmi-user-name command to be executed 33 | # Run a sample IBMi CL command every minute to send message to QSYSOPR 34 | */1 * * * * QSECOFR system "SNDMSG MSG(CRONJOB) TOUSR(QSYSOPR)" 35 | # Run a sample IBMi CL command every minute to send message to QSYSOPR and log any stdout/stderr messages to custom log file /tmp/ibmicommand.log. 36 | */1 * * * * QSECOFR system "SNDMSG MSG(CRONJOB) TOUSR(QSYSOPR)" >> /tmp/ibmicommand.log 2>&1 37 | ``` 38 | 39 | See crontab configuration sample links below for site that can teach you more about setting up your cron jobs via the crontab configration files. 40 | https://github.com/richardschoen/howtostuff/blob/master/installcronie.md#links 41 | 42 | ***Note: It appears that you must specify the user ID to run the selected job as. In the above example we are running the SNDMSG example as QSECOFR.*** 43 | ```Only /QOpenSys/etc/crontab and the files in /QOpenSys/etc/cron.d/ have a username field though. Ours on IBM i are prefixed with /QOpenSys obviously.``` 44 | 45 | Reading link for more info on running as a specific user. 46 | https://serverfault.com/questions/352835/crontab-running-as-a-specific-user 47 | 48 | # Make sure crontab file and cron directories are owned by root user for running system jobs 49 | 50 | Run the following commands from a SSH session to make sure root user (QSECOFR) owns the files and directories. Otherwise your crontab will not run correctly because of permission errors even though the crond daemon will start up. 51 | 52 | ``` 53 | cd /QOpenSys/etc 54 | chown qsecofr crontab 55 | chown qsecofr cron.d 56 | chown qsecofr cron.hourly 57 | ``` 58 | 59 | # Starting the crond daemon to run schedule jobs 60 | 61 | Log in to SSH as IBM i QSECOFR level user. ```QSECOFR or a user with *ALLOBJ authority.``` 62 | 63 | Type: ```crond``` and press enter. 64 | 65 | 66 | From a 5250 session, run ***WRKACTJOB SBS(QUSRWRK) JOB(QP0ZSPWP)*** and you should see the active server jobs and threads in the QUSRWRK subsystem. 67 | 68 | ``` 69 | -------------------------------------------------------------------------------- 70 | QP0ZSPWP QSECOFR BCI .0 PGM-crond SELW 71 | -------------------------------------------------------------------------------- 72 | ``` 73 | Tip: If your crontab jobs are not running, drill in to this job via ```option 5. Work with``` and then display the job log for the active crond daemon ```10. Display job log, if active, on job queue, or pending ```. Usually there will be an error listed if your crontab command line entries are bad or permissions aren't set right on your crond configuration files and directories. 74 | 75 | 76 | # Ending the crond daemon job 77 | 78 | Log in to SSH as IBM i QSECOFR level user. 79 | 80 | Type: ```kill `cat /QOpenSys/etc/crond.pid` ``` and press enter. 81 | 82 | # Start crond daemon job bash script - startcrond.sh 83 | 84 | This script can be used to start the crond background job as an active job in the QUSRWRK subsystem. 85 | 86 | ``` 87 | #!/QOpenSys/pkgs/bin/bash 88 | crond -s 89 | ``` 90 | 91 | # End crond daemon job bash script - endcrond.sh 92 | 93 | This script can be used to end the crond background job if it's active. It used the process id stored in file /QOpenSys/etc/crond.pid to locate and kill the system job. 94 | 95 | ``` 96 | #!/QOpenSys/pkgs/bin/bash 97 | kill `cat /QOpenSys/etc/crond.pid` 98 | ``` 99 | 100 | # Start crond daemon job from QSHEXEC CL command 101 | 102 | This CL command example utilizes the QSHEXEC command which is part of the QSHONI library for running QSH/PASE jobs from a regular IBM i job. https://github.com/richardschoen/qshoni 103 | 104 | ``` 105 | QSHONI/QSHEXEC CMDLINE('crond') LOGSTDOUT(*YES) 106 | ``` 107 | 108 | # End crond daemon job from QSHEXEC CL command 109 | 110 | This CL command example utilizes the QSHEXEC command which is part of the QSHONI library for running QSH/PASE jobs from a regular IBM i job. https://github.com/richardschoen/qshoni 111 | 112 | ``` 113 | QSHONI/QSHEXEC CMDLINE('kill ```cat /QOpenSys/etc/crond.pid```') LOGSTDOUT(*YES) 114 | ``` 115 | 116 | This document does not cover production best practices. Best practices should be addressed with your Administration team or by researching Cron security best practices. 117 | 118 | # Links 119 | 120 | Cronie Github Site 121 | 122 | https://github.com/cronie-crond/cronie 123 | 124 | Crontab configuration examples 125 | 126 | https://phoenixnap.com/kb/set-up-cron-job-linux 127 | 128 | https://corenominal.org/2016/05/12/howto-setup-a-crontab-file/ 129 | 130 | https://pimylifeup.com/cron-jobs-and-crontab/ 131 | 132 | Let me know if you have a favorite cron setup link. 133 | 134 | 135 | -------------------------------------------------------------------------------- /installgitbucketonibmi.md: -------------------------------------------------------------------------------- 1 | # How to install GitBucket on IBM i 2 | GitBucket is an open source Java based git server for IBM i. 3 | 4 | This GitBucket git server can host any of your git project source code and the server has many other features such as Wikis for documentation. 5 | 6 | GitBucket is a great way to keep all your git based source code in a single repository. 7 | 8 | When used in conjunction with iForgit (http://www.iforgit.com) as a native IBM i client, you have a complete source management solution for all of your open source language projects stored in the IFS and source members that are still managed via source physical files. iForgit works as a native command based interface for SEU, PDM, RDi and VS Code developers and can manage all your RPG, CL, COBOL and other classic IBM i source members. 9 | 10 | Note: iForGit is a commercial offering. 11 | 12 | ## Create IBM i GITBUCKET user profile 13 | 14 | Create a user profile named: GITBUCKET with QPGMR authority. 15 | 16 | Give it a password so you can log on as the user when initially starting GitBucket. 17 | 18 | After creating the profile view the profile via ```WRKUSRPRF GITBUCKET``` and make sure its home directory is: ```/home/GITBUCKET``` and the directory exists. 19 | 20 | If home directory dsoes not exist, run the following commands from 5250 to create the home directory for GITBUCKET user and set the user as owner of the home directory: 21 | 22 | ``` 23 | MKDIR DIR('/home/GITBUCKET') DTAAUT(*RWX) OBJAUT(*ALL) 24 | 25 | CHGOWN OBJ('/home/GITBUCKET') NEWOWN(GITBUCKET) RVKOLDAUT(*YES) SUBTREE(*ALL) 26 | ``` 27 | 28 | ## Visit the GitBucket site 29 | 30 | https://gitbucket.github.io/ 31 | 32 | ## Download the gitbucket.war file 33 | 34 | https://github.com/gitbucket/gitbucket/releases/download/4.37.2/gitbucket.war 35 | 36 | Or view most recent releases 37 | 38 | https://github.com/gitbucket/gitbucket/releases 39 | 40 | ## Log in as GITBUCKET to a SSH bash shell, QSH or QP2TERM, to create Gitbucket IFS dir with following commands: 41 | ``` 42 | cd / 43 | 44 | mkdir gitbucket 45 | ``` 46 | 47 | ## Upload the gitbucket.war file to the ```/gitbucket``` IFS directory using your favorite binary file transfer method 48 | 49 | ## Determine Current Default Java Version for 5250 Sessions (Mainly for Reference) 50 | ``` 51 | STRQSH 52 | 53 | java -version 54 | 55 | Output should look somethihg like this and should be 1.8.x at least: 56 | 57 | ------------------------------------------------------------------------------------ 58 | java version "1.8.0_161" 59 | Java(TM) SE Runtime Environment (build 8.0.5.10 - pap3280sr5fp10-20180214_01(SR5 FP10)) 60 | IBM J9 VM (build 2.9, JRE 1.8.0 OS/400 ppc-32 20180208_378436 (JIT enabled, AOT enabled) 61 | OpenJ9 - 39bb844 62 | OMR - c04ccb2 63 | IBM - 2321a81) 64 | JCL - 20180209_01 based on Oracle jdk8u161-b12 65 | ------------------------------------------------------------------------------------ 66 | ``` 67 | 68 | ## From a shell logged in as GITBUCKET user profile, attempt to start the GitBucket server with following commands: 69 | ``` 70 | cd /gitbucket 71 | 72 | java -jar gitbucket.war 73 | ``` 74 | Example to Start on alternate port 10001 75 | ``` 76 | cd /gitbucket 77 | 78 | java -jar gitbucket.war --port-10001 79 | ``` 80 | 81 | ## Wait a few minutes and try to access the GitBucket URL from your IBM i 82 | ```http://[hostname]:8080/``` User/pass: root/root 83 | 84 | Or altrenate port 85 | ```http://[hostname]:10001/``` User/pass: root/root 86 | 87 | ```Change root user password after initial set up``` 88 | 89 | ## Where are work app files created in IFS 90 | By default the database and all application files and repository locations get extracted to or created in the ```/home/[userid]/.gitbucket``` directory for the user who ran the gitbucket server. In our case it should be: ```/home/GITBUCKET/.gitbucket``` 91 | 92 | ***It might be a good idea to create a GITBUCKET IBM i user to run the server nder for consistency.*** 93 | 94 | ## See GitBucket site or GitBucket github site for more documentation 95 | 96 | https://gitbucket.github.io/ 97 | 98 | https://github.com/gitbucket/gitbucket 99 | 100 | ## Databases 101 | By default GitBucket uses an internal H2 database. You may want to install Postgres on your IBM i and use that as a database instead. See the GitBucket site for config instructions once you have Postgres installed on your IBM i. 102 | 103 | Feel free to use my instructions on this site to set up Postgres on IBM i. 104 | 105 | ## Using with the new Java 11 on IBM i if desired 106 | https://bitbucket.org/ibmi/opensource/src/master/docs/java11/JAVA11_EARLY_ACCESS.md 107 | 108 | ## Setting the Java 11 path in a bash or other shell 109 | ``` 110 | JAVA_HOME=/QOpenSys/pkgs/lib/jvm/openjdk-11/ 111 | export JAVA_HOME 112 | PATH=/QOpenSys/pkgs/lib/jvm/openjdk-11/bin:$PATH 113 | export PATH 114 | cd /gitbucket 115 | java -jar gitbucket.war 116 | ``` 117 | 118 | ## Native IBM i Git Client for Managing Source Files in Git 119 | http://www.iforgit.com 120 | 121 | Use your favorite editor: SEU, PDM, RDi and VS Code to edit your classic RPG, CL and COBOL source members and then use iForGit as a native CL driven git client. 122 | 123 | You'll make the auditors happy. 124 | -------------------------------------------------------------------------------- /installgunicornibmi.md: -------------------------------------------------------------------------------- 1 | # Installing Python gunicorn server on IBM i 2 | 3 | 4 | https://docs.gunicorn.org/en/stable/install.html 5 | 6 | Prerequisites 7 | 8 | Make sure all Python 3 yum packages installed on IBM i 9 | 10 | Make sure you have the mosgt recent libutil2 yum package installed (0.8.0.1 as of 6/7/2020) 11 | 12 | Install the following Python modules 13 | ``` 14 | pip3 install gunicorn 15 | pip3 install greenlet 16 | pip3 install evently 17 | ``` 18 | 19 | 20 | ***Async Workers*** 21 | You may also want to install Eventlet or Gevent if you expect that your application code may need to pause for extended periods of time during request processing. Check out the design docs for more information on when you’ll want to consider one of the alternate worker types. 22 | ``` 23 | Install greenlet and eventlet 24 | $ pip install greenlet # Required for both 25 | $ pip install eventlet # For eventlet workers 26 | $ pip install gunicorn[eventlet] # Or, using extra 27 | ***Optional*** 28 | $ pip install gevent # For gevent workers 29 | $ pip install gunicorn[gevent] # Or, using extra 30 | ``` 31 | 32 | gevent process was cancelled. Had to remove: /QOpenSys/pkgs/lib/python3.6/site-packages/zope* 33 | 34 | Link on why it takes so long to build gevent. Also how to install with verbose mode: 35 | ```pip install -vvv gevent``` 36 | 37 | Trying to reinstall gevent. Taking a while. Will see if it completes. 38 | 39 | 40 | 41 | Notes that pointed to libutil2 not being current (Thanks to Calvin) 42 | ``` 43 | Traceback (most recent call last): 44 | File "/QOpenSys/pkgs/bin/gunicorn", line 7, in 45 | from gunicorn.app.wsgiapp import run 46 | File "/QOpenSys/pkgs/lib/python3.6/site-packages/gunicorn/app/wsgiapp.py", line 9, in 47 | from gunicorn.app.base import Application 48 | File "/QOpenSys/pkgs/lib/python3.6/site-packages/gunicorn/app/base.py", line 11, in 49 | from gunicorn import util 50 | File "/QOpenSys/pkgs/lib/python3.6/site-packages/gunicorn/util.py", line 9, in 51 | import fcntl 52 | ImportError: rtld: 0712-001 Symbol libutil_flock was referenced 53 | from module /QOpenSys/pkgs/lib/python3.6/lib-dynload/fcntl.so(), but a runtime definition 54 | of the symbol was not found. 55 | rtld: 0712-002 fatal error: exiting. 56 | ``` 57 | What a good call to gunicorn on command line to verify installed correctly should look like after successful install: 58 | ``` 59 | Should look like this: 60 | gunicorn 61 | usage: gunicorn [OPTIONS] [APP_MODULE] 62 | gunicorn: error: No application module specified. (edited) 63 | ``` 64 | 65 | -------------------------------------------------------------------------------- /installmariadbonibmi.md: -------------------------------------------------------------------------------- 1 | # Install and configure MariaDB Database Server on IBM i 2 | 3 | Install MariaDB yum packages from IBM i ACS Open Source Package Management 4 | ``` 5 | Package list: 6 | mariadb 7 | mariadb-server 8 | ``` 9 | 10 | # Connecting via SSH terminal to complete install process 11 | Log in to SSH as IBM i QSECOFR level user to do server setup. 12 | 13 | If not started, start the bash shell by typing ***bash*** unless bash is already your default shell. 14 | 15 | # Setting the IP binding address and TCP port for the MariaDB server in my.cnf config file 16 | 17 | ## This step must be done before starting the server for the first time 18 | 19 | Use nano editor, vim or other editor to edit ***/QOpenSys/etc/mariadb/my.cnf*** file so the server will listen on TCP/IP addresses. We will enable access on all IP addresses. Also make a change to prevent problems with the `my.cnf.d` directory. If you prefer using the green screen you can use the following CL command to edit the configuration file: ```EDTF '/QOpenSys/etc/mariadb/my.cnf'``` 20 | 21 | Edit ***/QOpenSys/etc/mariadb/my.cnf*** 22 | Add the [mysqld] directive and the following 2 entries: bind-address and port: 23 | 24 | ``` 25 | [mysqld] 26 | bind-address=0.0.0.0 27 | port=3306 28 | ``` 29 | Comment out the `!includedir` directive to prevent a startup error if the `/QOpenSys/etc/mariadb/my.cnf.d` directory is missing. This directory can get deleted on startup when it's empty, then causing an error if `!includedir` requires it. 30 | ``` 31 | #!includedir /QOpenSys/etc/mariadb/my.cnf.d 32 | ``` 33 | 34 | Save the my.cnf file 35 | 36 | ***For a more secure server only listen on IP address 127.0.0.1/localhost*** 37 | 38 | **Also, the default port is 3306. I often change to a non-standard port like 33306 instead.** 39 | 40 | Example of what your actual ***/QOpenSys/etc/mariadb/my.cnf*** will look like after adding the bind-address and port entries. 41 | ``` 42 | # 43 | # This group is read both by the client and the server 44 | # use it for options that affect everything 45 | # 46 | [client-server] 47 | 48 | # 49 | # include *.cnf from the config directory 50 | # Comment out this directive if my.cnf.d is empty 51 | #!includedir /QOpenSys/etc/mariadb/my.cnf.d 52 | 53 | [mysqld] 54 | bind-address=0.0.0.0 55 | port = 3306 56 | ``` 57 | 58 | # First time database initialization in directory: /QOpenSys/var/lib/mariadb/data 59 | 60 | Run the following shell command line sequence to initialize the MariaDB database in directory: ***/QOpenSys/var/lib/mariadb/data*** 61 | ``` 62 | /QOpenSys/pkgs/bin/mysql_install_db 63 | ``` 64 | 65 | # Starting the MariaDB server job - mysqld 66 | 67 | Run the following mysqld_safe command to start MariaDB database server daemon. The server must be started before using the ***mysqladmin*** command to perform actions. 68 | https://dev.mysql.com/doc/refman/8.0/en/mysqld-safe.html 69 | 70 | ``` 71 | cd /QOpenSys/pkgs ; /QOpenSys/pkgs/bin/mysqld_safe --datadir=/QOpenSys/var/lib/mariadb/data 72 | ``` 73 | ***The MariaDB mysqld server startup will lock up the terminal window so you may want to start the MariaDB server job from a submitted job on the IBM i or possibly using the QSHEXEC command which is part of the QSHONI library (if you have it installed)*** https://github.com/richardschoen/qshoni 74 | 75 | ***Since the MariaDB mysqld server starts as a background thread job and locks up the terminal windows, you can probably just close the SSH/bash terminal window and the mysqld server daemon will stay running. (Need to Test)*** 76 | 77 | # Setting the MariaDB root user password after starting server for the first time 78 | The server must be running before setting the new root user password and using the mysqladmin command. 79 | 80 | ***First open a new SSH/bash terminal window (if you haven't already done so)*** since starting the server took over your previous terminal session and you also may have closed the previous terminal session as noted above since mysqld starts as a background job. 81 | 82 | Set root user password as desired with your own password. (Replace yournewpassword with the actual desired password.) 83 | ``` 84 | /QOpenSys/pkgs/bin/mysqladmin -u root password yournewpassword 85 | ``` 86 | 87 | # Stopping the MariaDB server job - mysqld 88 | 89 | The following command can be used from any bash session to stop the server. Make sure to specify your root user and yourpassword when shutting down the server 90 | ``` 91 | /QOpenSys/pkgs/bin/mysqladmin --no-defaults --user=root --password=yourpassword shutdown 92 | ``` 93 | 94 | # Checking for active MariaDB server instance 95 | 96 | From a 5250 session, run the ***WRKACTJOB*** command or to be more specific to PASE jobs run ***WRKACTJOB SBS(QUSRWRK) JOB(QP0ZSPWP)*** and you should see the active server jobs and threads in the QUSRWRK subsystem. The entry below shows what you should see if the MariaDB server is running. 97 | ``` 98 | -------------------------------------------------------------------------------- 99 | QP0ZSPWP RICHARD BCI .0 PGM-mysqld SELW 100 | -------------------------------------------------------------------------------- 101 | ``` 102 | 103 | # Checking for active MariaDB server port 104 | 105 | From a 5250 session, run the ***NETSTAT *CNN*** command to verify the server is listening on port 3306. You should see an entry for Local Port 3306 which tells you the server is listening for connections. 106 | ``` 107 | -------------------------------------------------------------------------------- 108 | Work with IPv4 Connection Status 109 | System: SYS 110 | Type options, press Enter. 111 | 3=Enable debug 4=End 5=Display details 6=Disable debug 112 | 8=Display jobs 113 | 114 | Remote Remote Local 115 | Opt Address Port Port Idle Time State 116 | * * 3306 000:05:22 Listen 117 | -------------------------------------------------------------------------------- 118 | ``` 119 | 120 | # Allow remote user access for MariaDB database development 121 | 122 | :round_pushpin: By default all MariaDB server access can only be done from apps running natively on the IBM i server using the localhost host name or 127.0.0.1 IP address. 123 | 124 | You can allow remote access to the MariaDB server from any host for the MariaDB root user or other users ***for development*** by running the ***mysql*** PASE command and a few related SQL commands. Make sure you know your MariaDB root user and password. You will be prompted for your password when you run the ***mysql*** command. 125 | ``` 126 | /QOpenSys/pkgs/bin/mysql -u root -p 127 | ``` 128 | After login to the mysql command line app, run the following SQL commands to allow access to the MariaDB instance from toolsets outside of localhost/127.0.0.1. ***Later for security purposes you can revoke this access so only the IBM i apps can access the MariaDB server.*** 129 | ``` 130 | use mysql; 131 | GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'YourPassword'; 132 | ``` 133 | If desired, run the following SQL query to see all the access entries for the MariaDB server. You should see the ***root*** user entry with a wildcard ***%*** for the host which means it should be able to access the server from anywhere. 134 | ``` 135 | select host,user from user; 136 | ``` 137 | The following results should show 138 | ``` 139 | +---------------------------------+------+ 140 | | host | user | 141 | +---------------------------------+------+ 142 | | % | root | 143 | | 127.0.0.1 | root | 144 | | ::1 | root | 145 | | localhost | | 146 | | localhost | root | 147 | | myibmi.com | | 148 | | myibmi.com | root | 149 | +---------------------------------+------+ 150 | ``` 151 | 152 | ***Note: If you have trouble connecting to the MariaDB instance from another computer after changing this setting, you may need to Stop and restart the MariaDB server after the permission change.*** 153 | 154 | Use Heidi, DBeaver or other MySQL/MariaDB client to connect to MariaDB database. 155 | ``` 156 | Host: IBMi host name or IP 157 | Port: 3306 158 | User: root 159 | Password: yourpassword 160 | ``` 161 | 162 | # Changing the MariaDB listening port to something other than 3306 163 | 164 | If desired, change the port that MariaDB server listens on to something other than 3306. This can be useful if you want to run multiple versions of MariaDB or you already have another MySql server running on your IBM i system. 165 | 166 | use nano editor, vim or other editor to edit ***/QOpenSys/etc/mariadb/my.cnf*** file 167 | 168 | Change port number or add a port entry in ***my.cnf*** 169 | 170 | ``` 171 | Change port number or add a port entry: 172 | 173 | port = 3306 174 | 175 | save my.cnf 176 | ``` 177 | 178 | Stop and restart MariaDB server and it should listen on the new port. 179 | 180 | Now refer to standard MariaDB documentation as needed. 181 | 182 | # MariaDB Server Security - IMPORTANT 183 | 184 | This document is mainly a quick getting started document for testing and development. 185 | 186 | This document does not cover all production best practices, but listed below are a few suggestions. Security best practices should be discussed and addressed with your security team or by researching MySql/MariaDB security best practices. 187 | 188 | Listed below are a few things that I can think of top of mind for keeping your MariaDB data safe: 189 | * Limit access to the MariaDB data directories from the IFS. Perhaps create a MYSQL or MARIADB IBM i user that has access to the data directory ***/QOpenSys/var/lib/mariadb/data*** only and limit that users authority. Then when starting the MariaDB server submit the startup job as the MYSQL/MARIDB user to job queue QSYSNOMAX. 190 | * Make sure server is only listening on localhost/127.0.0.1 191 | * Make sure you've established a root password, but don't use it for production apps. 192 | * Create application MariaDB users/password so the root user does not get exposed. 193 | * Back up your MariaDB server regularly using one of the methods below. 194 | * Stop server and back up your MariaDB data directory regularly. ***/QOpenSys/var/lib/mariadb/data*** 195 | * Or leave MariaDB server running and use accepted MySql/MariaDB backup procedures. There are 3rd party MariaDB/MySQL backup tools available or you can use the ***mysqldump*** command. Search for ***mysql data backup*** or here's a sample link: https://serverguy.com/servers/how-to-backup-mysql-database 196 | 197 | # Submitting MariaDB Server Startup via QSHEXEC CL Command 198 | The mysqld server startup command can be submitted to job queue QSYSNOMAX and will run in the QUSRWRK subsystem unless your IBM i is configured differently. The server job needs to be submitted to a multi-threaded subsystem so QSYSMOAX/QUSRWRK is the perfect combination. After submitting you can use the WRKACTJOB and NETSTAT example above to see if the server jobs and ports are active. 199 | 200 | The QSHEXEC command can be used to call QSH/PASE jobs from a regular IBM i job and handles all the threading set up and log capture. https://www.github.com/richardschoen/qshoni 201 | 202 | ``` 203 | SBMJOB CMD(QSHONI/QSHEXEC 204 | CMDLINE('/QOpenSys/pkgs/bin/mysqld_safe 205 | --datadir=/QOpenSys/var/lib/mariadb/data') 206 | PRTSTDOUT(*YES) PRTSPLF(STRMARIADB)) 207 | JOB(STRMARIADB) JOBQ(QSYSNOMAX) JOBMSGQFL(*WRAP) 208 | ``` 209 | 210 | # Submitting MariaDB Server Shutdown/End via QSHEXEC CL Command 211 | The mysqld server shutdown can be run interactively or submitted to job queue QSYSNOMAX and will run in the QUSRWRK subsystem unless your IBM i is configured differently. Make sure to specify your MariaDB root user and password. This job will typically only run a few seconds so it could be run without SBMJOB if desired. A shutdown operation can be delayed if there are several client threads connected to the MariaDB instance so you might need to explore other possible shutdown options such as killing the process using its process id if you have regular issues shutting down your MariaDB server. However shutting down a process via the kill command or ```ENDJOB *IMMED``` on the IBM i can cause data corruption if a server is shutdown while transactions are running. 212 | 213 | ``` 214 | SBMJOB CMD(QSHONI/QSHEXEC 215 | CMDLINE('/QOpenSys/pkgs/bin/mysqladmin --no-defaults 216 | --user=root --password=YourPassword shutdown') 217 | SETPKGPATH(*YES) PRTSTDOUT(*YES) PRTSPLF(ENDMARIADB)) 218 | JOB(ENDMARIADB) JOBQ(QSYSNOMAX) JOBMSGQFL(*WRAP) 219 | ``` 220 | 221 | # Hard Kill the MariaDB mysqld Instance Immediately 222 | If you want to kill your MariaDB instance by using its process id file, locate the mysqld instance process id file in directory ***/QOpenSys/var/lib/mariadb/data***. 223 | 224 | The file name will have a .pid extension and a name which will most likely match your IBM i system host name. 225 | 226 | In this example we are trying to kill the mysqld server on a server named: ***youribmihostname.com*** so the .pid file name will be: ***youribmihostname.com.pid*** 227 | 228 | If you are more comfortable doing an ENDJOB command from a regular IBM i 5250 session, do a WRKACTJOB to identify the mysqld job as mentioned above and do an ```ENDJOB *IMMED``` to kill the running MariaDB server instance immediately. 229 | 230 | ``` 231 | kill ```cat /QOpenSys/var/lib/mariadb/data/youribmihostname.com.pid``` 232 | ``` 233 | 234 | # Links 235 | 236 | MariaDB Site 237 | 238 | http://www.mariadb.com/ 239 | 240 | MariaDB Knowledgebase 241 | 242 | http://mariadb.com/kb 243 | 244 | MariaDB Documentation 245 | 246 | https://mariadb.com/kb/en/documentation/ 247 | 248 | Tutorial Link 249 | 250 | https://powerwire.eu/hello-maria 251 | 252 | 253 | -------------------------------------------------------------------------------- /installmkdocsibmi.md: -------------------------------------------------------------------------------- 1 | # How to install MKDocs on IBM i 2 | MKDocs is an open source Python static site generator for creating documentation using Markdown syntax documents. 3 | 4 | No database required. And technically no web server either since the **build** option creates a static, standalone HTML site. 5 | 6 | This is a quick way to establish a departmental knowledgebase with shareable system and process documentation. 7 | 8 | A MKDocs project directory structure could also be turned into a git project if desired so the entire site would be versioned in a git repository. 9 | 10 | ## Visit the MKDocs site 11 | https://www.mkdocs.org 12 | 13 | ## Pre-requisites 14 | 15 | Make sure Python 3 is installed and running on your IBM i system from the IBM Open Source Package Management options in IBM ACS. 16 | 17 | https://www.ibm.com/support/pages/getting-started-open-source-package-management-ibm-i-acs 18 | 19 | :pushpin: This usually means installing the entire Python 3 option set and gcc compiler via ACS, including python3-devel to make sure python.h is found. 20 | ``` 21 | gcc-aix 22 | gcc-cplusplus-aix 23 | gcc-cpp-aix 24 | python3 25 | python3-Pillow 26 | python3-asn1crypto 27 | python3-bcrypt 28 | python3-cffi 29 | python3-cryptography 30 | python3-dateutil 31 | python3-devel 32 | python3-ibm_db 33 | python3-idna 34 | python3-itoolkit 35 | python3-jinja2 36 | python3-lxml 37 | python3-markupsafe 38 | python3-numpy 39 | python3-pandas 40 | python3-paramiko 41 | python3-pip 42 | python3-psutil 43 | python3-psycopg2 44 | python3-pycparser 45 | python3-pynacl 46 | python3-pyodbc 47 | python3-pytz 48 | python3-pyyaml 49 | python3-pyzmq 50 | python3-rpm 51 | python3-scikit-learn 52 | python3-scipy 53 | python3-setuptools 54 | python3-six 55 | python3-tkinter 56 | python3-wheel 57 | 58 | Or you could install gcc and python3 using the following commands from bash: 59 | yum install gcc* 60 | yum install python3* 61 | ``` 62 | 63 | ## Install MKDocs using pip3 64 | 65 | Log in to IFS from an SSH bash shell session, QSH or QP2TERM, run the following commands to install MKDocs as part of your default Python 3.6 environment installed in /QOpenSys/pkgs/bin 66 | 67 | **Note:** We will set the path so Python 3.6 is picked up from /QOpenSys/pkgs/bin 68 | 69 | ``` 70 | ## Set the path so /QOpenSys/pkgs/bin is first in the list 71 | PATH=/QOpenSys/pkgs/bin:/QOpenSys/usr/bin:/usr/ccs/bin:/QOpenSys/usr/bin/X11:/usr/sbin:.:/usr/bin 72 | export PATH 73 | 74 | ## Run pip upgrade to make sure pip3 is current. (Version 19, 20 or newer after upgrade should be good. Mine is 20.3.3 as of 12/19/2020) 75 | ## If pip is not current then the correct current version Python package versions may not install. 76 | pip3 install --upgrade pip 77 | 78 | ## Check to make sure Python shows V3.6.x 79 | python3 -V (to verify we are seeing Python 3.6.x. Current version 3.6.12 as of 12/19/2020) 80 | 81 | ## Run the MKDocs install process 82 | pip3 install mkdocs 83 | 84 | ``` 85 | When install completes you should see something like the following 86 | ``` 87 | Successfully built regex 88 | Installing collected packages: regex, nltk, lunr, mkdocs 89 | Successfully installed lunr-0.5.8 mkdocs-1.1.2 nltk-3.5 regex-2020.11.13 90 | ``` 91 | 92 | Install themes - Themes can be tweaked as desired. We will install the Bootswatch theme and then select yeti below when we edit the mkdocs.yml site configuration file. 93 | ``` 94 | pip3 install mkdocs-bootswatch 95 | ``` 96 | **Note: There may be additional items needed that my system already had, but I have not identified if there are other specific requirements.** 97 | 98 | ## Make sure all your pip3 packages are installed correctly 99 | ``` 100 | ## Run following command to check pip3 packages for Python3 101 | pip3 check 102 | ``` 103 | If it runs as expected you will see 104 | ``` 105 | No broken requirements found. 106 | ``` 107 | If any errors occur you will need to probably do a package update for the pip3 package out of sync or in error. 108 | Then re-run ***pip check*** to make sure all package requirements are now in sync. 109 | ``` 110 | ## This example shows how to run an upgrade if livereload/tornado shows out of sync. 111 | pip3 reinstall --upgrade 112 | Ex: pip3 reinstall --upgrade livereload 113 | ``` 114 | 115 | ## Create and run your first documentation site on port 8555 116 | ``` 117 | cd / 118 | 119 | mkdocs new docproject1 120 | 121 | cd /docproject1 122 | 123 | mkdocs serve --dev-addr=0.0.0.0:8555 124 | ``` 125 | Visit your new documentation site in the browser: http://ibmiaddress:8555 126 | 127 | ## If you get errors during startup of MkDocs 128 | ``` 129 | ## I had an issue where the server didn't lke the livereload version and tornado versions. 130 | ##I got the following error:** 131 | raise VersionConflict(dist, req).with_context(dependent_req) 132 | pkg_resources.ContextualVersionConflict: (tornado 6.1 (/QOpenSys/pkgs/lib/python3.6/site-packages), Requirement.parse('tornado<6'), {'livereload'}) 133 | 134 | ## The following pip upgrade fixed livereload and then I could run the mkdocs server 135 | ## It uninstalled tornado v6.1 and installed v5.1.1. On another server I already have 136 | ## tornado 6.1 and mkdocs works fine. Not sure why, but this solved the issue. 137 | pip3 install --upgrade livereload 138 | ``` 139 | 140 | ## Setting default host address and theme info in mkdoc.yml site config file 141 | 142 | edit /docproject1/mkdocs.yml file and add the following contents. Tailor them to your liking. 143 | 144 | ``` 145 | site_name: My IBM i Documentation 146 | dev_addr: 0.0.0.0:8555 147 | theme: yeti 148 | nav: 149 | - Home: index.md 150 | - About: about.md 151 | ``` 152 | These settings assume you will plan to create a new about.md markdown page in your project directory. 153 | 154 | ## Submitting MKDocs serve to Run as A Batch Job 155 | 156 | The following command submits the MKDOCS job to run as a batch server in subsystem QSYSWRK via job queue QSYSNOMAX 157 | ``` 158 | SBMJOB CMD(QSHEXEC CMDLINE('cd /docproject1;mkdocs serve') PRTSPLF(MKDOCS) PRTUSRDTA(*YES)) JOB(MKDOCS) JOBQ(QSYSNOMAX) JOBMSGQFL(*WRAP) 159 | ``` 160 | In order to use the QSHEXEC command to run the MKDocs server or other QShell/PASE commands, you must install the command from the following site: https://github.com/richardschoen/QshOni 161 | 162 | ## Building and Deploying your Static Site 163 | 164 | This example builds a site directory from a MkDocs project directory named: /docproject1. Once the site is built, simply deploy the /docproject1/site folder to your web site or view the site from a network directory by opening index.html. 165 | 166 | Then you don't need anything special to access your site other than a web browser. 167 | 168 | ``` 169 | cd / 170 | 171 | cd /docproject1 172 | 173 | mkdoc build 174 | ``` 175 | 176 | That's it. Your static site is ready to go. 177 | 178 | ## See MKDocs site for more documentation on building your documentation sites with markdown files 179 | https://www.mkdocs.org 180 | 181 | ## Styling Your Docs with Themes 182 | https://www.mkdocs.org/user-guide/styling-your-docs/ 183 | 184 | ## 3rd Party Themes 185 | https://github.com/mkdocs/mkdocs/wiki/MkDocs-Themes 186 | -------------------------------------------------------------------------------- /installpostgresonibmi.md: -------------------------------------------------------------------------------- 1 | # Install and configure Postgresql DB Server on IBM i 2 | 3 | Install postgres yum packages from IBM i ACS Open Source Package Management 4 | ``` 5 | Package list: 6 | postgresql12 ***(postgresql12 may be the only item you need to select to include all packages)*** 7 | postgresql12-contrib 8 | postgresql12-devel 9 | postgresql12-docs 10 | postgresql12-libecpg 11 | postgresql12-libpgtypes 12 | postgresql12-libpq 13 | postgresql12-server 14 | ``` 15 | 16 | Create IBM i user: ***POSTGRES*** and give it a password. It's important the user is named POSTGRES because the Postgresql server needs a default user of POSTGRES. At least that was my experience with it. (Also give it *ALLOBJ access for now. You can probably remove *ALLOBJ later and possibly even disable the IBM i POSTGRES user. ***Not tested yet.***) 17 | 18 | Log in to SSH as IBM i user ***POSTGRES*** to do server setup. 19 | 20 | If not started, start the bash shell by typing ***bash*** unless bash is already your default shell. 21 | 22 | Run the following shell command line sequence to initialize postgres database in the /postgres IFS directory location 23 | ``` 24 | cd / 25 | 26 | mkdir postgres 27 | 28 | export PGDATA=/postgres 29 | 30 | initdb -E UTF-8 -D /postgres 31 | ``` 32 | 33 | After initdb you should see the following message: 34 | ``` 35 | Success. You can now start the database server using: 36 | pg_ctl -D /postgres -l logfile start 37 | ``` 38 | 39 | ***Do not start server yet until after you modify /postgres/postgresql.conf*** 40 | 41 | Use nano editor, vim or other editor to edit ***/postgres/postgresql.conf*** file so the server will listen on TCP/IP addresses. We will enable access on all IP addresses 42 | ``` 43 | edit /postgres/postgresql.conf 44 | uncomment listen_addresses and and change to: listen_addresses = '*' 45 | uncomment the port = 5432 entry. 46 | save postgresql.conf 47 | ``` 48 | 49 | Run the following command to start postgres database server. 50 | ``` 51 | pg_ctl -D /postgres -l logfile start 52 | ``` 53 | 54 | You should see the following messages: 55 | ``` 56 | waiting for server to start.... done 57 | server started 58 | ``` 59 | 60 | This following command can be used to stop the server. 61 | ``` 62 | pg_ctl -D /postgres -l logfile stop 63 | ``` 64 | 65 | From a 5250 session, run WRKACTJOB and you should see the active server jobs and threads in the QUSRWRK subsystem 66 | ``` 67 | -------------------------------------------------------------------------------- 68 | QP0ZSPWP POSTGRES BCI .0 PGM-postgres SELW 69 | QP0ZSPWP POSTGRES BCI .0 PGM-postgres SELW 70 | QP0ZSPWP POSTGRES BCI .0 PGM-postgres SELW 71 | QP0ZSPWP POSTGRES BCI .0 PGM-postgres SELW 72 | QP0ZSPWP POSTGRES BCI .0 PGM-postgres SELW 73 | QP0ZSPWP POSTGRES BCI .0 PGM-postgres SELW 74 | QP0ZSPWP POSTGRES BCI .0 PGM-postgres SELW 75 | -------------------------------------------------------------------------------- 76 | ``` 77 | 78 | From a 5250 session, run "NETSTAT *CNN" to verify the server is listening on port 5432. You should see an entry for Local Port 5432 which tells you the server is listening for connections. 79 | ``` 80 | -------------------------------------------------------------------------------- 81 | Work with IPv4 Connection Status 82 | System: SYS1 83 | Type options, press Enter. 84 | 3=Enable debug 4=End 5=Display details 6=Disable debug 85 | 8=Display jobs 86 | 87 | Remote Remote Local 88 | Opt Address Port Port Idle Time State 89 | * * 5432 000:05:22 Listen 90 | -------------------------------------------------------------------------------- 91 | ``` 92 | 93 | Allow remote access to server. You can change this by editing ***/postgres/pg_hba.conf*** 94 | 95 | Add following entry to the pg_hba.conf file: 96 | ``` 97 | host all all 0.0.0.0/0 password 98 | ``` 99 | Note: This will enable password checking. You'll need to set a new password for the ***postgres*** user on the Postgresql server. See below. 100 | 101 | Save pg_hba.conf. 102 | 103 | Stop and then start Postgresql server as described previously. 104 | 105 | From shell command line, create demo postgres database using the following command line command: 106 | ``` 107 | createdb ibmidemo 108 | ``` 109 | 110 | The psql command utility can be used to provide permissions and do other server related maintenance. 111 | 112 | For now we will just allow access for the postgres user to our new database as an example. 113 | We will also set a password for the postgres user. This sample uses 'postgres2020' for the password. 114 | You should use a more secure password. 115 | ***NOTE: You should also review the Postgres site for appropriate Postgres security measures.*** 116 | 117 | Start psql utility 118 | ``` 119 | psql 120 | ``` 121 | 122 | Type the following sql and press Enter to set database access for postgres database user: 123 | ``` 124 | grant all privileges on database ibmidemo to postgres; 125 | ``` 126 | 127 | Type the following sql and press Enter to set the database server password for the postgres database user. My example uses a password of: ***postgres2020*** but you can use what you want for a password. 128 | ``` 129 | alter user postgres with password 'postgres2020'; 130 | ``` 131 | 132 | Type: ***quit*** and press enter to exit the psql utility. 133 | 134 | 135 | Use Heidi, DBeaver or other Postgresql client to connect to Postgres database. 136 | ``` 137 | Host: IBMi host name or IP 138 | Port: 5432 139 | User: postgres 140 | Password: postgres2020 141 | Database: ibmidemo 142 | ``` 143 | 144 | If desired, change the port that Postgresql server listens on to something other than 5432. 145 | 146 | use nano editor, vim or other editor to edit ***/postgres/postgresql.conf*** file 147 | 148 | ``` 149 | Change port number. 150 | Ex: port = 60432 151 | ``` 152 | 153 | save postgresql.conf 154 | 155 | Stop and restart Postgres server 156 | 157 | Now refer to standard Postgresql documentation as needed. 158 | 159 | # Links 160 | 161 | Backup and Restore PostgreSQL Databases from Command Line 162 | https://github.com/richardschoen/howtostuff/blob/master/postgres-backup-restore.md 163 | 164 | Postgresql Site 165 | https://www.postgresql.org 166 | 167 | Role postgres does not exist 168 | https://dba.stackexchange.com/questions/221663/psql-fatal-role-postgres-does-not-exist 169 | 170 | Yips Site - old stuff but might be worth reading 171 | http://yips.idevcloud.com/wiki/index.php/Databases/PostgreSQL 172 | 173 | Postgresql 12 docs 174 | https://www.postgresql.org/docs/12/index.html 175 | -------------------------------------------------------------------------------- /installpythonfastapi.md: -------------------------------------------------------------------------------- 1 | # How to install Python FastAPI Web Framework and Get Started on IBM i 2 | FastAPI is a Python high performance web framework 3 | 4 | Uvicorn is a lightning fast ASGI web server 5 | 6 | ## Visit the FastAPI site 7 | https://fastapi.tiangolo.com 8 | 9 | ## Visit the Uvicorn site 10 | http://www.uvicorn.org 11 | 12 | ## Sample site from Niels Liisberg 13 | https://github.com/NielsLiisberg/Python-FastAPI-demo 14 | 15 | ## Installing on IBM i 16 | 17 | **Pre-requisite** 18 | 19 | Make sure all ```Python 3``` options are installed by the ``Open Source Package Management``` menu option in ACS 20 | 21 | Log in to an IBM i SSH terminal session and make sure bash is the current shell 22 | 23 | **Install fastapi - latest** 24 | 25 | ```pip3 install fastapi``` 26 | 27 | **Install fastapi for Python 3.9 - Use fastapi Version 0.110.3** 28 | Did a stepped install of each of these versions. You might just be able to install ```0.110.3``` 29 | ```pip3 install fastapi==0.83.0``` 30 | ```pip3 install fastapi==0.84.0``` 31 | ```pip3 install fastapi==0.89.0``` 32 | ```pip3 install fastapi==0.95.0``` 33 | ```pip3 install fastapi==0.99.1``` 34 | ```pip3 install fastapi==0.100.1``` 35 | ```pip3 install fastapi==0.108.0``` 36 | ```pip3 install fastapi==0.110.3``` 37 | 38 | **Install uvicorn (The lightning fast ASGI server). This will be our web app server component** 39 | 40 | ```pip3 install uvicorn``` 41 | 42 | **Note: Dont install with the [standard] option. This will possibly cause errors when trying to build some of the wheels.** 43 | 44 | ## Your First App in Less Than a Minute (Also with OpenAPI Docs). 45 | 46 | Create an IFS folder for your project. 47 | ``` 48 | cd / 49 | 50 | mkdir /pythonfastapi 51 | ``` 52 | 53 | Create a new main.py file with the following lines: 54 | 55 | ``` 56 | from typing import Optional 57 | 58 | from fastapi import FastAPI 59 | 60 | app = FastAPI() 61 | 62 | 63 | @app.get("/") 64 | def read_root(): 65 | return {"Hello": "World"} 66 | 67 | 68 | @app.get("/items/{item_id}") 69 | def read_item(item_id: int, q: Optional[str] = None): 70 | return {"item_id": item_id, "q": q} 71 | ``` 72 | 73 | 74 | ## Running Your App from the IBM i SSH/Bash Command Line 75 | 76 | ``` 77 | cd /pythonfastapi 78 | 79 | uvicorn main:app --reload --port 3434 80 | ``` 81 | 82 | This will start your app on port 3434. The results should look like the following. And the web app server will restart any time a page change is made. 83 | 84 | ``` 85 | INFO: Will watch for changes in these directories: ['/home/RICHARD/richard/pythonfastapi'] 86 | INFO: Uvicorn running on http://0.0.0.0:3434 (Press CTRL+C to quit) 87 | INFO: Started reloader process [2530954] using watchgod 88 | INFO: Started server process [2530956] 89 | INFO: Waiting for application startup. 90 | INFO: Application startup complete. 91 | ``` 92 | 93 | ## Exposing App to the Web 94 | If you plan to expose your web app to the Internet, it's probably a good idea to set up an NGINX web server as a web front end that also uses SSL for secure communications. NGINX can proxy/pass all web traffic to youe Uvicorn server. 95 | 96 | Note: It's possible Uvicorn can be exposed without using NGINX, but I would recommend exploring this more on the Uvicorn web site and doing appropriate research before you expose your app server to the web. http://www.uvicorn.org/deployment 97 | 98 | 99 | ## Trying out your sample app from a web browser 100 | 101 | The following URL will display the Hello World response 102 | 103 | ```http://[hostname]:3434``` 104 | 105 | The following URL will display the /items route response 106 | 107 | ```http://[hostname]:3434/items/1/q=SampleQuery``` 108 | 109 | Displaying Open API/Swagger Documentation and Testing API 110 | 111 | ```http://[hostname]:3434/docs``` 112 | 113 | Displaying ReDoc Documentation and Testing API 114 | 115 | ```http://[hostname]:3434/redoc``` 116 | 117 | ## Sample Packages Needed for Fast API 118 | ``` pip3.9 install pyodbc``` 119 | ``` pip3.9 install itoolkit``` 120 | ``` pip3 install fastapi==0.83.0``` (You may just be able install 0.110.3) 121 | ``` pip3 install fastapi==0.110.3``` 122 | ``` pip3 install uvicorn``` 123 | ``` pip3.9 install flask``` (Flask not actually needed for FastAPI, but I use flask as well so I commonly install Flask as well.) 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /installwikijs.md: -------------------------------------------------------------------------------- 1 | # Basic Installation for WikiJS on IBM i 2 | 3 | I have not written any specific instructions at this point. But here's a basic guide that might work for you. 4 | 5 | **Use the Windows install as a base download** 6 | https://docs.requarks.io/install/windows 7 | 8 | Made sure to have at least Node 12 loaded and SQLite 3 from IBM Open Source packages. 9 | ```Current version of Node is V22.x.``` 10 | 11 | Manually download the latet WikiJS app file. I used the Windows package and it worked fine since it's Node based 12 | https://github.com/Requarks/wiki/releases/latest/download/wiki-js-windows.tar.gz 13 | 14 | **Upload tar file to the /tmp off the root of IFS** 15 | 16 | ```/wiki-js-windows.tar.gz``` 17 | 18 | **Another option to get the file quickly is to run the wget command from an SSH terminal** 19 | ``` 20 | wget https://github.com/Requarks/wiki/releases/latest/download/wiki-js-windows.tar.gz -P /tmp 21 | ``` 22 | **Run this from bash shell, qp2term or possibly strqsh** 23 | 24 | ``` 25 | mkdir /wikijs 26 | mkdir /wikijs/database 27 | mkdir /wikijs/backups 28 | cd /tmp 29 | tar xzf wiki-js-windows.tar.gz -C /wikijs 30 | (After tar completes change to wikijs dir) 31 | cd /wikijs 32 | ``` 33 | 34 | ***Ran this to rebuild SQLite3 driver binary I am using on IBM i (Only worked for node 12)*** 35 | 36 | ```npm rebuild sqlite3``` 37 | 38 | ❗You will need to use postgres for your database. The above npm rebuild fails for sqllite3 on V7R5. Postgres seems to work fine. 39 | 40 | ***Copy sample config file to actual config file*** 41 | 42 | ```cp /wikijs/config.sample.yml /wikijs/config.yml``` 43 | 44 | ***Edit config.yml file via your favorite PC file editor or WRKLNK I suppose.*** 45 | 46 | ``` 47 | Db 48 | type: sqlite 49 | storage: /wikijs/database/database.sqlite 50 | ``` 51 | 52 | ***Run WikiJs*** 53 | 54 | ```node server``` 55 | 56 | ***Hit site via browser and config*** 57 | 58 | ```http://systemip:3000``` 59 | 60 | ***Use the rest of the basic WikiJS site instructions*** 61 | ``` 62 | https://docs.requarks.io/guide/intro 63 | ``` 64 | -------------------------------------------------------------------------------- /linuxcommands.md: -------------------------------------------------------------------------------- 1 | # Linux and PASE AIX Commands 2 | 3 | ***touch*** - Create a new empty file. 4 | ``` 5 | touch filename.txt 6 | ``` 7 | 8 | ***chmod*** - change file permissions. 9 | ``` 10 | Full permissions example: chmod 777 filename.txt 11 | ``` 12 | 13 | ***find*** - find files 14 | 15 | https://www.linode.com/docs/tools-reference/tools/find-files-in-linux-using-the-command-line/ 16 | 17 | ``` 18 | Ex: find /home -name *.jpg Find all .jpg files in the /home and sub-directories. 19 | ``` 20 | 21 | ***dhclient*** - request a new IP address from DHCP 22 | 23 | https://www.cyberciti.biz/faq/howto-linux-renew-dhcp-client-ip-address/ 24 | 25 | ``` 26 | Renew IP address example: sudo dhclient -r 27 | ``` 28 | 29 | ***ls*** - List files 30 | 31 | https://techyaz.com/linux/11-examples-ls-command-list-files-linux/ 32 | 33 | ``` 34 | List all files: ls * 35 | 36 | List all PDF files: ls *.pdf 37 | 38 | List all files wide foramt: ls -l 39 | 40 | ``` 41 | 42 | ***cp*** - Copy files and directories 43 | 44 | https://www.rapidtables.com/code/linux/cp.html 45 | 46 | ``` 47 | Copy file from one path to another: cp /dir1/file.txt /dir2/file.txt 48 | ``` 49 | 50 | ***mkdir*** - Make directory 51 | 52 | https://www.computerhope.com/unix/umkdir.htm 53 | 54 | ``` 55 | Ex: mkdir /demo 56 | ``` 57 | 58 | ***rmdir*** - Remove directory 59 | 60 | https://www.computerhope.com/unix/urmdir.htm 61 | 62 | ``` 63 | ex: rmdir /dirname 64 | ``` 65 | 66 | ***ifconfig*** - Check IP addresses 67 | 68 | https://www.journaldev.com/30052/linux-ifconfig-command-examples 69 | 70 | ``` 71 | Ex: ifconfig 72 | ``` 73 | 74 | ***ip*** - Newer Replacement for ifconfig - Check IP addresses 75 | 76 | https://computingforgeeks.com/ifconfig-vs-ip-usage-guide-on-linux/#:~:text=%20ifconfig%20vs%20ip%20usage%20guide%20on%20Linux,ip%20and%20ifconfig%20commands.%20For%20this...%20More%20 77 | 78 | ``` 79 | Ex: ip address (list ip addresses) 80 | ``` 81 | 82 | ***systemctl*** - Linux Services 83 | 84 | ``` 85 | List all services active or not: 86 | systemctl list-units --all --type=service --no-pager 87 | ``` 88 | 89 | # Additional samples links 90 | 91 | https://www.journaldev.com/24613/linux-ps-command 92 | 93 | crontab 94 | 95 | awk 96 | 97 | grep 98 | 99 | sudo 100 | 101 | cp 102 | 103 | export 104 | 105 | nohup 106 | 107 | alias 108 | 109 | zip 110 | 111 | unzip 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /nginx-ibmi-without-allobject-auth.md: -------------------------------------------------------------------------------- 1 | # Configure NGINX with specific user without user needing *ALLOBJ Authority 2 | User was seeing the following error in their NGINX log file when trying to start or restart the NGINX server via: 3 | 4 | Regular NGINX startup command 5 | ```nginx -c /qopensys/etc/nginx/nginx.conf``` 6 | -or- 7 | NGINX reload command 8 | ```nginx -s reload``` 9 | 10 | Errors showed up in the log file in file: ```/QOpenSys/var/log/nginx/error.log``` 11 | Accessing error.log from 5250 command line: ```WRKLNK '/QOpenSys/var/log/nginx/error.log'``` 12 | ``` 13 | 2024/05/21 13:00:46 [notice] 3215038#1: signal process started 14 | 2024/05/21 13:00:46 [alert] 3214934#1: recvmsg() failed (13: Permission denied) 15 | 2024/05/21 13:00:46 [alert] 3215039#1: recvmsg() failed (13: Permission denied) 16 | 2024/05/21 13:00:46 [alert] 3215041#1: recvmsg() failed (13: Permission denied) 17 | 2024/05/21 13:00:46 [alert] 3215042#1: recvmsg() failed (13: Permission denied) 18 | ``` 19 | This seems to be related to setting up an appropriate user profile to run the NGINX server and threads under. 20 | 21 | By default the main thread user will be the ```user who started the NGINX server```. And worker thread jobs run under user profile: ```QTMHHTTP``` by default. 22 | 23 | What we want is for the main thread and worker threads to run under the ```same user profile```. 24 | 25 | # NGINX Configuration Steps 26 | Using latest NGINX version on IBM i, here's what I got to work which can eliminate the *ALLOBJ requirement I believe by running all NGINX jobs using the same user profile: 27 | - I created a userid. Let's call it ```NGINX1```. 28 | - I gave the user ```*NONE``` for special authorities. 29 | - I did some IFS permission setting for ```NGINX1``` for NGINX log dirs with the following CL command from a 5250 session. 30 | ``` 31 | CHGAUT OBJ('/qopensys/var/log/nginx') 32 | USER(NGINX1) 33 | DTAAUT(*RWX) 34 | OBJAUT(*ALL) 35 | SUBTREE(*ALL) 36 | ``` 37 | - I added the ```user NGINX1;``` at the top of my NGINX config for the user instead of leaving the default of: ```user nobody;``` 38 | - I submit the NGINX startup to run as user ```NGINX1```. Should also work to start NGINX via command line if logged in to SSH terminal as ```NGINX1``` user. 39 | I use the QSHEXEC command to submit my NGINX Process. (QSHEXEC is part of my QShell on i utilities) 40 | 41 | Example of submitting NGINX startup using QSHEXEC command: 42 | ``` 43 | SBMJOB CMD(QSHONI/QSHEXEC CMDLINE('nginx -c /qopensys/etc/nginx/nginx.conf') PRTSTDOUT(*YES) PRTSPLF(NGINX)) 44 | JOB(NGINX) JOBQ(QUSRNOMAX) USER(NGINX1) 45 | ``` 46 | 47 | - The server starts as user ```NGINX1``` and it skips the SETUID process because NGINX1 is already specified in the config file. 48 | (The setuid skip thing was actually somewhat documented in the setuid api) 49 | - NGINX version used: v1.23.0 50 | ``` 51 | $ nginx -v 52 | Result: nginx version: nginx/1.23.0 53 | ``` 54 | - In my case a number of DB tables had to be authorized as well so my web apps could access those tables. Unless you have *PUBLIC authority set on the objects you will also need to authorize objects for access by user ```NGINX1```. 55 | 56 | The takeaway is you can run NGINX without *ALLOBJ with current NGINX. At least it worked for me. 57 | 58 | Feel free to open a GitHub issue if you run into any issues with this example. 59 | 60 | # Additional Reading 61 | Interestingly it would appear that if I start the NGINX server as the user specified in the "user USERID;" setting in the NGINX.CONF file the NGINX user does not need *ALLOBJ authority. 62 | I'm basing my theory on this: 63 | https://www.ibm.com/docs/api/v1/content/ssw_ibm_i_73/apis/qsysetui.htm 64 | 65 | I was reading this old NGINX thread on the IBMi open source site: 66 | https://bitbucket.org/ibmi/opensource/issues/141/run-nginx-and-php-fpm-as-user-qtmhhttp 67 | 68 | Install NGINX on IBM i 69 | https://www.ibm.com/support/pages/how-install-nginx-ibm-i 70 | 71 | IBM OSS Docs - Installing NGINX 72 | https://ibmi-oss-docs.readthedocs.io/en/latest/nginx/README.html# 73 | 74 | NGINX Documentation 75 | https://docs.nginx.com 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /nodejs20_register.md: -------------------------------------------------------------------------------- 1 | # Register nodejs20 with alternatives as an alternate version of node 2 | When I installed nodejs20 via the yum installer/Open Source Package Management to my IBM i, it didn't register itself as an alternative, so I used the following commands from a ssh/bash shell to set up the alternatives command for nodejs20. 3 | 4 | ## List the alternatives to see if nodejs20 shows up 5 | Run the following command: ```update-alternatives --list node``` 6 | ``` 7 | /QOpenSys/pkgs/lib/nodejs10/bin/node 8 | /QOpenSys/pkgs/lib/nodejs12/bin/node 9 | /QOpenSys/pkgs/lib/nodejs14/bin/node 10 | /QOpenSys/pkgs/lib/nodejs16/bin/node 11 | /QOpenSys/pkgs/lib/nodejs18/bin/node 12 | ``` 13 | nodejs20 did not show as an alternative. 14 | 15 | ## Install nodejs20 as an alternative along with associated apps (slave apps) 16 | The following command should be copied and pasted to an ssh/bash session as a single command 17 | ``` 18 | update-alternatives --install /QOpenSys/pkgs/node node /QOpenSys/pkgs/lib/nodejs20/bin/node 20 --slave /QOpenSys/pkgs/bin/npm npm /QOpenSys/pkgs/lib/nodejs20/bin/npm --slave /QOpenSys/pkgs/bin/npx npx /QOpenSys/pkgs/lib/nodejs20/bin/npx 19 | ``` 20 | nodejs20 now shows as an alternative when running ```update-alternatives --list node``` 21 | 22 | ``` 23 | /QOpenSys/pkgs/lib/nodejs10/bin/node 24 | /QOpenSys/pkgs/lib/nodejs12/bin/node 25 | /QOpenSys/pkgs/lib/nodejs14/bin/node 26 | /QOpenSys/pkgs/lib/nodejs16/bin/node 27 | /QOpenSys/pkgs/lib/nodejs18/bin/node 28 | /QOpenSys/pkgs/lib/nodejs20/bin/node 29 | ``` 30 | 31 | ## You can also query to make sure the slave apps are set 32 | Run the following command: ```update-alternatives --query node``` 33 | 34 | This should display each node version and it's slave apps (associated apps to the selected node version). 35 | 36 | This example shows node18 and node20 are installed. 37 | ``` 38 | Alternative: /QOpenSys/pkgs/lib/nodejs18/bin/node 39 | Priority: 18 40 | Slaves: 41 | npm /QOpenSys/pkgs/lib/nodejs18/bin/npm 42 | npx /QOpenSys/pkgs/lib/nodejs18/bin/npx 43 | 44 | Alternative: /QOpenSys/pkgs/lib/nodejs20/bin/node 45 | Priority: 20 46 | Slaves: 47 | npm /QOpenSys/pkgs/lib/nodejs20/bin/npm 48 | npx /QOpenSys/pkgs/lib/nodejs20/bin/npx 49 | ``` 50 | 51 | ## nodejs20 can now be set as an default version of node system wide 52 | Set nodejs20 as the default node version: 53 | ```update-alternatives --set node /QOpenSys/pkgs/lib/nodejs20/bin/node``` 54 | 55 | ## Check the current default node version now 56 | Run following command: ```node -v``` and it should show: ```v20.8.1``` 57 | 58 | ## Check the current default npm version now 59 | Run following command: ```npm -v``` and it should show: ```v10.1.0``` 60 | 61 | ## Check the current default npx version now 62 | Run following command: ```npx -v``` and it should show: ```v10.1.0``` 63 | -------------------------------------------------------------------------------- /postgres-backup-restore.md: -------------------------------------------------------------------------------- 1 | # Backup and Restore PostgreSQL Database from Command Line 2 | This document is a short guide that covers backing up and restoring Postgres databases using the ```pg_dump``` and ```pg_restore``` PostgreSQL commands. These utilities are available on Windows, Linux, Mac, IBM i and any other operating system that supports PostgreSQL. 3 | 4 | ❗If you are an IBM i user and using PostgreSQL on i, you can find the ```PGDUMP``` and ```PGRESTORE``` CL commmand examples on the following page link listed below to integrate PostgreSQL with your traditional IBM i jobs.. These samples work in conjunction with the QShell on i utilities. https://github.com/richardschoen/QshOni/blob/master/samples 5 | 6 | See example usage of the ```PGDUMP``` and ```PGRESTORE``` IBM i CL command wrappers for pg_dump and pg_restore below. https://github.com/richardschoen/howtostuff/blob/master/postgres-backup-restore.md#ibm-i-cl-commands-pgdump-and-pgrestore-which-are-helpers-for-backuprestore-of-postgresql-database-on-i 7 | 8 | ❗```In my examples I am using mydatabase and mydatabase2, You would supply your own database names.``` 9 | 10 | ❗I also use the ```--verbose``` switch to list operations, but this switch is optional. 11 | 12 | ## Backup/Dump database named: mydatabase to tar file /tmp/mydatabase.tar using pg_dump 13 | Use pg_dump to backup/dump your database in tar format with the ```-F t``` switch. 14 | ```export PGPASSWORD=password1``` 15 | ```pg_dump -F t -d mydatabase -p 5432 -U postgres --verbose > /tmp/mydatabase.tar``` 16 | or with host name 17 | ```pg_dump --h localhost F t -d mydatabase -p 5432 -U postgres --verbose > /tmp/mydatabase.tar``` 18 | 19 | ❗If the tar file is 0 bytes, then something failed on you dump/backup operation. Otherwise the backup should have been successful with no errors. Next we will use the tar command to verify the tar file is not corrupted. 20 | 21 | ## Verify backup tar file /tmp/mydatabase.tar with tar command 22 | ```tar -tvf /tmp/richard.tar``` 23 | 24 | It should list your files in the tar file something like this: 25 | ``` 26 | -rw------- 0 postgres postgres 2898 Jun 22 16:45 toc.dat 27 | -rw------- 0 postgres postgres 50 Jun 22 16:45 3192.dat 28 | -rw------- 0 postgres postgres 5 Jun 22 16:45 3190.dat 29 | -rw------- 0 postgres postgres 3149 Jun 22 16:45 restore.sql 30 | ``` 31 | 32 | ❗If the tar file list completes successfully your tar file should technically be error-free, but no guarantees. 33 | 34 | ## Restore postgres database with the original database name and create it using pg_restore if the database does not already exist 35 | This example restores the database: ```mydatabase``` using it's original name and also creates it on the PostgreSQL server. The ```-C``` switch auto-creates the database but you have to specify an existing database name with the ```-d``` switch or you'll get an error when restoring. So the examples I found said to use the ```-d "postgres"``` setting when using ```-C``` to create the database on restore because the ```postgres``` database should always exist. 36 | 37 | ❗You'll notice that user ```postgres``` is the owner of the database so you may need to assign appropriate permissions after restoring the database. 38 | 39 | ❗Make sure database doesn't exist on target system. or you'll need to drop it or rename it first in psql utility. ```DROP DATABASE mydatabase;``` 40 | ```export PGPASSWORD=password1``` 41 | ```pg_restore -C -d "postgres" -p 5432 -U postgres --verbose "/tmp/mydatabase.tar"``` 42 | or with host name 43 | ```pg_restore -C -h localhost -d "postgres" -p 5432 -U postgres --verbose "/tmp/mydatabase.tar"``` 44 | 45 | If there are no errors, the command completed successfully and the mydatabase PostgreSQL database should now exist. 46 | 47 | ## Restore postgres database with the original database name and replace database contents using pg_restore when database already exists 48 | This example restores the database: ```mydatabase``` using it's original name and also clears the existing database on the PostgreSQL server before restore. The ```--clean``` switch clears the existing database before restore. 49 | 50 | ```pg_restore -d "mydatabase" -p 5432 -U postgres --clean --verbose "/tmp/mydatabase.tar"``` 51 | 52 | ❗If the database already exists, you can use the ```--clean``` switch to clear all tables and restore the entire backup to the original database. 53 | 54 | If there are no errors, the command completed successfully and the refreshed mydatabase PostgreSQL database should now exist with all the restored tables and other objects for the PostgreSQL database. 55 | 56 | ## Restore backup of mydatabase database as different database: mydatabase2 using pg_restore 57 | ❗First you need to create the new mydatabase2 database as an empty database before restoring 58 | 59 | ### Create new mydatabase2 database using createdb command 60 | Create new empty database: ```mydatabase2``` 61 | 62 | ```createdb -U postgres -W mydatabase2``` 63 | 64 | ### Restore mydatabase database from tar file as mydatabase2 using pg_restore 65 | ```pg_restore -d "mydatabase2" -p 5432 -U postgres --verbose "/tmp/mydatabase.tar"``` 66 | 67 | If there are no errors, the command completed successfully and the mydatabase2 PostgreSQL database should now exist with all the restored tables and other objects for the PostgreSQL database that was saved in ```/tmp/mydatabase.tar```. 68 | 69 | ## IBM i CL commands PGDUMP and PGRESTORE which are helpers for backup/restore of PostgreSQL database on i 70 | The PGDUMP and PGRESTORE commands are wrappers around the QSHBASH utility for running pg_dump and pg_restore to backup and restore a Postgres database on IBM i 71 | 72 | ❗The PGDUMP and PGRESTORE CL commands and programs PGDUMPC/PGRESTOREC are located at the following link and must be created on your IBM i system. 73 | https://github.com/richardschoen/QshOni/blob/master/samples 74 | 75 | ❗The QShell on i library ```QSHONI``` is also a requirement to use these CL commands. 76 | 77 | QShell on i install info: 78 | https://github.com/richardschoen/QshOni 79 | 80 | ### Backup/Dump database named: mydatabase to tar file /tmp/mydatabase.tar with PGDUMP CL command 81 | Use the PGDUMP CL command to backup/dump your database in tar format with the ```-F t``` switch. 82 | 83 | Example of backing up mydatabase to /tmp/mydatabase.tar via PGDUMP command which calls pg_dump 84 | ``` 85 | PGDUMP DATABASE(mydatabase) 86 | OUTPUTFILE('/tmp/mydatabase.tar') 87 | OPTIONS('-p 5432 -U postgres --verbose') 88 | PROMPT(*NO) 89 | REPLACE(*YES) 90 | ``` 91 | Example of backing up mydatabase to /tmp/pgbackup directory with auto-timestamped IFS file name ```/tmp/pgbackup/mydatabase-yyyymmdd-hhmmssfff.tar``` via PGDUMP command which calls pg_dump. *DBTEMPDATETIME creates the file in the ```/tmp/pgbackup``` directory or whatever value exists in data area ```QGPL/PGBACKDIR``` 92 | ``` 93 | PGDUMP DATABASE(mydatabase) 94 | OUTPUTFILE(*DBTEMPDATETIME) 95 | OPTIONS('-p 5432 -U postgres --verbose') 96 | PROMPT(*NO) 97 | REPLACE(*YES) 98 | ``` 99 | 100 | If there are no errors, the backup/dump command completed successfully and the tar file was verified. 101 | 102 | ### Restore database named: mydatabase from tar file /tmp/mydatabase.tar with PGRESTORE CL command if database does not exist yet 103 | Use the PGRESTORE CL command to restore your database from a tar formatted file if it does not already exist and you want to restore it to the same or a new system. 104 | 105 | Example of restoring mydatabase from /tmp/mydatabase.tar via PGRESTORE command which calls pg_restore to create and restore the database. 106 | You can specify the -C option to create the database and then just specify ```postgres``` as the database because apparently the -C switch requires an existing database when run and the ```postgres``` database always exists. Then the database ```mydatabase``` should get created and restored correctly. 107 | ``` 108 | PGRESTORE DATABASE(postgres) 109 | INPUTFILE('/tmp/mydatabase.tar') 110 | OPTIONS('-C -p 5432 -U postgres --verbose') 111 | PROMPT(*YES) 112 | DSPSTDOUT(*YES) 113 | ``` 114 | If there are no errors, the command completed successfully and the mydatabase PostgreSQL database should now exist. 115 | 116 | ### Restore database named: mydatabase from tar file /tmp/mydatabase.tar with PGRESTORE CL command if database already exists - replace 117 | Use the PGRESTORE CL command to restore your database from a tar formatted file and replace your existing database of the same name if you want to clear and refresh an existing database from a backup. 118 | 119 | Example of restoring mydatabase from /tmp/mydatabase.tar via PGRESTORE command which calls pg_restore to clear and overwrite existing database. 120 | ❗If the database already exists, you can use the ```--clean``` switch to clear all tables and restore the entire backup to the original database. 121 | 122 | ``` 123 | PGRESTORE DATABASE(mydatabase) 124 | INPUTFILE('/tmp/mydatabase.tar') 125 | OPTIONS('-p 5432 -U postgres --clean --verbose') 126 | PROMPT(*YES) 127 | DSPSTDOUT(*YES) 128 | ``` 129 | 130 | If there are no errors, the command completed successfully and the refreshed mydatabase PostgreSQL database should now exist with all the restored tables and other objects for the PostgreSQL database. 131 | 132 | ### Restore database named: mydatabase from tar file /tmp/mydatabase.tar as mydatabase2 with PGRESTORE CL command 133 | Use the PGRESTORE CL command to restore your database from a tar formatted file as a new name. The database with the new name must first be created. 134 | 135 | This example call to QSHBASH calls the PostgreSQL utility ```createdb``` to create a new empty database named: ```mydatabase2``` 136 | 137 | ```QSHONI/QSHBASH CMDLINE('createdb -U postgres -p 5432 mydatabase2') DSPSTDOUT(*YES) PRTSPLF(CREATEDB)``` 138 | 139 | Example of restoring ```mydatabase``` from ```/tmp/mydatabase.tar``` as ```mydatabase2``` via PGRESTORE command which calls pg_restore. 140 | ``` 141 | PGRESTORE DATABASE(mydatabase2) 142 | INPUTFILE('/tmp/mydatabase.tar') 143 | OPTIONS('-p 5432 -U postgres --verbose') 144 | PROMPT(*YES) 145 | DSPSTDOUT(*YES) 146 | ``` 147 | 148 | If there are no errors, the command completed successfully and the mydatabase2 PostgreSQL database should now exist with all the restored tables and other objects for the PostgreSQL database that was saved in ```/tmp/mydatabase.tar```. 149 | 150 | ## Useful psql commands 151 | 152 | ### Starting psql not connected to a specific database 153 | ```export PGPASSWORD=password1``` 154 | ```psql -U postgres -p 5432``` 155 | 156 | ### Starting psql connected to a specific database 157 | ```export PGPASSWORD=password1``` 158 | ```psql -U postgres -p 5432 -d mydatabase``` 159 | 160 | ### List databases 161 | ```\list - list database info``` 162 | 163 | ### List all database names with SQL 164 | ```SELECT datname FROM pg_database;``` 165 | 166 | ### List all tables in the database that are not part of pg_catalog or information_schema schema 167 | This is a good way to see what tables exist in the database under various schema's. Tables will normally exist in the ```public``` schema. 168 | ``` 169 | SELECT * 170 | FROM pg_catalog.pg_tables 171 | WHERE schemaname != 'pg_catalog' AND 172 | schemaname != 'information_schema'; 173 | ``` 174 | 175 | ### Check if the selected table exists in the specified schema 176 | This is a good way to see what tables exist in the selected schema. This example checks for table: ```accounts``` in the ```public``` schema. 177 | ``` 178 | SELECT * 179 | FROM pg_catalog.pg_tables 180 | WHERE schemaname = 'public' AND 181 | tablename = 'accounts'; 182 | ``` 183 | 184 | ## My Python Postgres Backup and Restore Scripts 185 | Check out the following repository for a set of Python Backup and Restore scripts I created that utilize the backup and restore commands listed in this article. These scripts should work with PostgreSQL on any platform. 186 | 187 | Python Postgres Backup Utility 188 | https://github.com/richardschoen/pythonpostgresbackup 189 | 190 | ## Misc / Reading Links 191 | 192 | ### Backup and Restore of PostgreSQL Database 193 | https://www.tecmint.com/backup-and-restore-postgresql-database 194 | 195 | ### Restoring from a tar file 196 | https://serverfault.com/questions/115051/how-to-restore-postgresql-database-from-tar-file 197 | 198 | ### psql commmands 199 | https://www.atlassian.com/data/admin/how-to-list-databases-and-tables-in-postgresql-using-psql 200 | 201 | ``` 202 | \l - lists database 203 | \c dbname - connect to database 204 | \q - quit psql 205 | ``` 206 | 207 | ### Dropping a database in psql 208 | ``` 209 | drop database dbname 210 | commit 211 | ``` 212 | 213 | ### Problems with the -C option on restore 214 | https://stackoverflow.com/questions/40784677/pg-restore-with-c-option-does-not-create-the-database 215 | 216 | ### Postgres Backups 217 | https://www.dbvis.com/thetable/a-complete-guide-to-pg-dump-with-examples-tips-and-tricks/ 218 | 219 | ### Varchar and text fields with no specific length 220 | https://dba.stackexchange.com/questions/20254/postgresql-data-type-text-vs-varchar-without-length 221 | https://www.sprinkledata.com/blogs/postgresql-text-vs-varchar-choosing-the-right-data-type-for-your-database 222 | 223 | -------------------------------------------------------------------------------- /pythonpipibmi.md: -------------------------------------------------------------------------------- 1 | # Using pip on IBM i to install with compiles 2 | This doc describes some changes required when compiling Python pip modules for V7R4 and above. 3 | 4 | ## IBM i Prior to V7R4 5 | gcc-6 can be used during installation of Python pip modules that need compilation. 6 | 7 | ## IBM i V7R4 and above 8 | gcc-10 needs to be used when installing Python pip modules that need compilation. 9 | 10 | Example command line to install pip module: 11 | ``` 12 | CC='gcc-10 -pthread' CXX='g++-10 -pthread' python3.9 -m pip install 13 | ``` 14 | 15 | Make your own directory with the gcc 10 symlinks and add it to the PATH, eg so you don't need the CC= or CXX= 16 | ``` 17 | mkdir mydir 18 | ln -s /QOpenSys/pkgs/bin/gcc-10 mydir/gcc 19 | ln -s /QOpenSys/pkgs/bin/g++-10 mydir/g++ 20 | PATH=$PWD/mydir:$PATH 21 | ``` 22 | Ideally use your own home directory for the shortcuts and add to path 23 | ``` 24 | mkdir ~/bin 25 | ln -s /QOpenSys/pkgs/bin/gcc-10 ~/bin/gcc 26 | ln -s /QOpenSys/pkgs/bin/g++-10 ~/bin/g++ 27 | PATH=$PWD/~/bin:$PATH 28 | ``` 29 | 30 | -------------------------------------------------------------------------------- /pythonwebgitvieweribmi.md: -------------------------------------------------------------------------------- 1 | # Installing Python Web Based Git Repository Viewer - Klaus 2 | Klaus is a Python based git repository viewer for viewing local file system repositories. 3 | 4 | Klaus is a nice companion web based git source viewer if using iForGit to version control your classic IBM i source physical files in IFS based git repositories. And you don't want to send them to a remote server such as GitHub, GitLab or Bitbucket. 5 | 6 | For this use-case we will be viewing repository source changes stored in the IBM IFS file system that may have been committed by **iForGit IBM i 5250 Git Client** users. (http://www.mobigogo.net/files/docs/iforgit) However any IFS based git repository can be viewed from a browser if listed in the runtime configuration. 7 | 8 | Slogan from the Github site: 9 | **klaus: a simple, easy-to-set-up Git web viewer that Just Works** 10 | 11 | Github site for Klaus 12 | https://github.com/jonashaag/klaus 13 | 14 | # Installing from PyPI 15 | 16 | PyPI Site 17 | https://pypi.org/project/klaus 18 | 19 | pip3 command line to install Klaus server 20 | ``` 21 | pip3 install klaus 22 | ``` 23 | 24 | pip3 command line to upgrade Klaus server 25 | ``` 26 | pip3 install klaus --upgrade 27 | ``` 28 | 29 | 30 | # Security 31 | There is no user security on the web server component by default. However the specified **repositories are read-only**. 32 | 33 | If you need some basic security you will possibly want to implement this with the Gunicorn web server and nginx. 34 | 35 | **Sample nginx config file listed at bottom of article** (https://github.com/richardschoen/howtostuff/blob/master/pythonwebgitvieweribmi.md#links) 36 | 37 | See site for already available instructions: https://github.com/jonashaag/klaus 38 | 39 | **TODO:** Gunicorn set up for IBM i. 40 | 41 | # Prerequisites 42 | Make sure all Python 3 and gcc yum packages installed on IBM i via IBM ACS Open Source Package Management and **/QOpenSys/pkgs/bin** is in SSH search path 43 | 44 | ``` 45 | # Set path to open source packages 46 | export PATH=/QOpenSys/pkgs/bin:$PATH 47 | 48 | # Install all Python 3 packages via yum command (Don't forget the asterisk *) 49 | yum install python3* 50 | 51 | # Install gcc compiler 52 | yum install gcc 53 | 54 | # Install git 55 | yum install git 56 | 57 | # Update Python pip installer (version should go from 9.0.1 to 21.1.1 or later during the process) 58 | pip3 install --upgrade pip 59 | 60 | # Install the following Python modules 61 | pip3 install klaus 62 | ``` 63 | 64 | **If you get any errors during install, please note them here by opening an issue.** 65 | 66 | # Running Klaus git viewer server from qsh/pase/bash 67 | 68 | This example runs the Klaus git server over repositories /gitrepostest/GITTEST123 and /gitrepostest/GITTEST124 on HTTP port 4646 and is listening on all IP addresses. 69 | 70 | Running Klaus server on local IBM i and listening on any address (Insecure without nginx) 71 | ``` 72 | klaus --host 0.0.0.0 --port 4646 /gitrepostest/GITTEST123 /gitrepostest/GITTEST124 73 | ``` 74 | 75 | Running Klaus server with nginx. Use localhost/127.0.0.1 since nginx will proxy calls to Klaus 76 | ``` 77 | klaus --host 127.0.0.1 --port 4646 /gitrepostest/GITTEST123 /gitrepostest/GITTEST124 78 | ``` 79 | 80 | # Running Klaus git viewer server from SBMJOB/QSHEXEC 81 | 82 | This example runs the Klaus git server over repositories GITTEST123 and GITTEST124 on HTTP port 4646 and is listening on all IP addresses. 83 | 84 | The background job is submitted via SBMJOB using the QSHEXEC command. (Must install QSHONI library from: http://www.github.com/richardschoen/qshoni) 85 | 86 | Running Klaus server on local IBM i and listening on any address. (Insecure without nginx) 87 | ``` 88 | SBMJOB CMD(QSHONI/QSHEXEC CMDLINE('klaus --host 0.0.0.0 --port 4646 /gitrepostest/GITTEST123 /gitrepostest/GITTEST124') 89 | SETPKGPATH(*YES) PRTSPLF(GITVIEWER)) JOB(GITVIEWER) JOBQ(QUSRNOMAX) JOBMSGQFL(*WRAP) 90 | ``` 91 | Running Klaus server with nginx. Use localhost/127.0.0.1 since nginx will proxy calls to Klaus 92 | ``` 93 | SBMJOB CMD(QSHONI/QSHEXEC CMDLINE('klaus --host 127.0.0.1 --port 4646 /gitrepostest/GITTEST123 /gitrepostest/GITTEST124') 94 | SETPKGPATH(*YES) PRTSPLF(GITVIEWER)) JOB(GITVIEWER) JOBQ(QUSRNOMAX) JOBMSGQFL(*WRAP) 95 | ``` 96 | 97 | # Accessing Klaus Git Viewer Web Site 98 | Log in from any web browser with the following url and port where sysnameorip is your IBM i host IP address and port is the specified port number. 99 | 100 | Example using port 4646: 101 | ```http://sysnameorip:4646``` 102 | 103 | # Finding GITVIEWER job so you can end it via option 4 ( Use ENDJOB OPTION(*IMMED) ) 104 | ``` 105 | WRKACTJOB JOB(GITVIEWER) 106 | ``` 107 | 108 | # Sample nginx config for Klaus with user/password security enabled 109 | 110 | | :exclamation: When using nginx to proxy access to the Klaus server, make sure Klaus listens on IP 127.0.0.1 instead of 0.0.0.0 | 111 | |-----------------------------------------| 112 | 113 | | :exclamation: You should set up your nginx server to use SSL. This example does not. | 114 | |-----------------------------------------| 115 | 116 | Sample nginx config file: **nginx-klaus.conf** 117 | 118 | ``` 119 | #user nobody; 120 | worker_processes 1; 121 | 122 | #error_log logs/error.log; 123 | #error_log logs/error.log notice; 124 | #error_log logs/error.log info; 125 | 126 | #pid logs/nginx.pid; 127 | 128 | events { 129 | worker_connections 1024; 130 | } 131 | 132 | http { 133 | include mime.types; 134 | default_type application/octet-stream; 135 | 136 | #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 137 | # '$status $body_bytes_sent "$http_referer" ' 138 | # '"$http_user_agent" "$http_x_forwarded_for"'; 139 | 140 | #access_log logs/access.log main; 141 | 142 | sendfile on; 143 | #tcp_nopush on; 144 | 145 | #keepalive_timeout 0; 146 | keepalive_timeout 65; 147 | 148 | #--------------------------------------------------- 149 | # Non SSL Reverse Proxy for Git Viewer 150 | # This example passes the incoming request on port 151 | # 4647 to the nginx server and passes the request 152 | # to internal Klaus Git Viewer localhost address on port 4646 153 | # 154 | # Enable user security 155 | # - Uncomment auth_basic and auth_basic_user_file to enable user auth. 156 | # - .httpasswd file must exist if uncommenting/enabling basic user/password checking. 157 | # - Set up nginx .httpasswd file. See following web link for nginx user/pass setup example 158 | # https://www.digitalocean.com/community/tutorials/how-to-set-up-password-authentication-with-nginx-on-ubuntu-14-04 159 | #--------------------------------------------------- 160 | server { 161 | listen 4647; 162 | #auth_basic "Enter Git Viewer User Info"; 163 | #auth_basic_user_file /QOpenSys/etc/nginx/.htpasswd; 164 | server_name mygitviewer.com; 165 | 166 | location / { 167 | proxy_pass http://localhost:4646; 168 | proxy_pass_request_headers on; 169 | proxy_set_header Host $host; 170 | proxy_set_header X-Real-IP $remote_addr; 171 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 172 | #proxy_redirect off; 173 | proxy_cookie_domain localhost 127.0.0.1; 174 | proxy_http_version 1.1; 175 | proxy_set_header Connection ""; 176 | } 177 | 178 | error_page 404 /404.html; 179 | 180 | # redirect server error pages to the static page /50x.html 181 | # 182 | error_page 500 502 503 504 /50x.html; 183 | location = /50x.html { 184 | root html; 185 | } 186 | 187 | } 188 | 189 | } 190 | ``` 191 | 192 | # Links 193 | See the Klaus site for further documentation 194 | https://github.com/jonashaag/klaus 195 | 196 | Nginx user/password file set up 197 | https://www.digitalocean.com/community/tutorials/how-to-set-up-password-authentication-with-nginx-on-ubuntu-14-04 198 | 199 | 200 | -------------------------------------------------------------------------------- /richard-favoritetools.md: -------------------------------------------------------------------------------- 1 | # Richard's Favorite Tools and Sites 2 | This is a list of my favorite tools. You might find it useful when you're tooling up. 3 | 4 | if you have a suggestion, drop me a note: richard@richardschoen.net 5 | 6 | ## Development 7 | 8 | DBeaver - Database Tool - Java based. 9 | https://dbeaver.io/download 10 | 11 | Visual Studio Code. 12 | https://code.visualstudio.com 13 | 14 | Geany Editor. 15 | https://www.geany.org 16 | 17 | Notepad++. 18 | https://notepad-plus-plus.org/downloads/ 19 | 20 | SSHFS - Visual Studio Code Plugin for SSH File Access. 21 | https://marketplace.visualstudio.com/items?itemName=Kelvin.vscode-sshfs 22 | 23 | Filezilla - FTP Client. 24 | https://filezilla-project.org 25 | 26 | CyberDuck - Cloud Storage Access for Mac/Windows. 27 | https://cyberduck.io 28 | 29 | MountainDuck - Mount cloud drives. 30 | https://mountainduck.io 31 | 32 | Remote Desktop Manager. 33 | https://devolutions.net 34 | 35 | Hex Workshop - Hex Editing. 36 | http://www.hexworkshop.com 37 | 38 | NSBasic - App Studio for Mobile Development. 39 | https://www.nsbasic.com 40 | 41 | 42 | ## IBM i/ AS400 Technical Stuff 43 | 44 | IBM Access - Client Solutions (Emulator and ODBC Drivers). 45 | https://www.ibm.com/support/pages/ibm-i-access-client-solutions 46 | 47 | Code for IBM i - Visual Studio Code Plugin. 48 | https://github.com/halcyon-tech/vscode-ibmi 49 | 50 | GitBucket Git Server - Java based. 51 | https://gitbucket.github.io 52 | 53 | QShell on i - Run QSH/PASE Apps from Traditional RPG/CL. 54 | https://github.com/richardschoen/qshoni 55 | 56 | Work with IBM i - Windows Replacement for PDM. 57 | https://github.com/richardschoen/workwithibmipdm. 58 | 59 | TN5250J - 5250 Emulator - Java. 60 | http://tn5250j.org 61 | 62 | Jasper Reports Server. 63 | https://community.jaspersoft.com 64 | 65 | 66 | ## IBM i Blogs and Periodicals and Docs 67 | 68 | Richard Schoen Blog. 69 | http://blog.richardschoen.net 70 | 71 | IBM i Open Source (OSS) Documentation. 72 | https://ibmi-oss-docs.readthedocs.io/en/latest/README.html 73 | 74 | Midrange.com. - Online IBM i Content and Forums. 75 | https://midrange.com. 76 | 77 | MCPress. - IBM i Books and Weekly Newsletter. 78 | https://www.mcpress.com 79 | 80 | IT Jungle - IBM i Newsletter. 81 | https://www.itjungle.com 82 | 83 | Scott Klement - IBM i related articles and content. 84 | https://www.scottklement.com 85 | 86 | Built on Power 87 | https://builtonpower.com 88 | 89 | Simon Hutchinson - IBM i on Power Technical Blog. 90 | https://www.rpgpgm.com. 91 | 92 | 93 | ## Documentation / Presentation 94 | 95 | Greenshot Screen Capture. 96 | https://getgreenshot.org 97 | 98 | Draw.io Diagramming 99 | https://drawio-app.com 100 | 101 | Record Screen, Edit and Save as GIF. 102 | https://www.screentogif.com 103 | 104 | Camtasia/Snagit - Screen Capture and Video Editing. 105 | https://www.techsmith.com 106 | 107 | OBS - Open Broadcasting Video Studio 108 | https://obsproject.com 109 | 110 | Cross Platform Audio Recording. 111 | https://www.audacityteam.org 112 | 113 | Help and Manual and HelpXPlain- Create Help Documentation and Tutorials. 114 | https://www.helpandmanual.com. 115 | 116 | Markdown Monster - Markdown Editor (Windows). 117 | https://markdownmonster.west-wind.com 118 | 119 | HelpNDoc - Help Authoring. 120 | https://www.helpndoc.com 121 | 122 | ## Misc. 123 | 124 | JSON Placeholder - Free fake API for testing and prototyping. 125 | https://jsonplaceholder.typicode.com 126 | 127 | Postman - REST API testing. 128 | https://www.postman.com 129 | 130 | ## Virtual Machine Platforms 131 | 132 | VMware. 133 | https://www.vmware.com 134 | 135 | QEMU. 136 | https://www.qemu.org 137 | 138 | UTM - Mac wrapper around QEMU. 139 | https://mac.getutm.app 140 | 141 | Parallels. 142 | https://www.parallels.com 143 | 144 | ProxMox 145 | https://www.proxmox.com. 146 | 147 | Virtual Box. 148 | https://www.virtualbox.org 149 | 150 | OSBoxes - Prebuild Linux Virtual Machines for various flavors. 151 | https://www.osboxes.org 152 | 153 | ## Security and Antivirus 154 | 155 | KeePass Password Safe. 156 | https://keepass.info 157 | 158 | Sophos Antivirus - Free Home Version (I've used Sophos for over 10 years). 159 | https://home.sophos.com/en-us. 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /setdefaultpaseuser.md: -------------------------------------------------------------------------------- 1 | # Set default PASE IBM i shell for individual user 2 | This shows you how to set the default PASE user. I generally set my user profile to use the bash shell as a default. 3 | 4 | ``` 5 | -- set current user's shell to bash 6 | CALL QSYS2.SET_PASE_SHELL_INFO('*CURRENT', '/QOpenSys/pkgs/bin/bash'); 7 | 8 | -- set a specific user's shell to bash 9 | -- (requires *SECADM special auth plus *USE and *OBJMGT to the user profile) 10 | CALL QSYS2.SET_PASE_SHELL_INFO('THATUSER', '/QOpenSys/pkgs/bin/bash'); 11 | 12 | -- set the default shell which is returned for users that do not have 13 | -- (requires *SECADM special auth plus *USE and *OBJMGT to QSYS) 14 | CALL QSYS2.SET_PASE_SHELL_INFO('*DEFAULT', '/QOpenSys/pkgs/bin/bash'); 15 | ``` 16 | 17 | #Useful Links 18 | https://techchannel.com/SMB/08/2017/be-like-a-turtle 19 | 20 | 21 | https://stackoverflow.com/questions/23913957/set-default-pase-ibm-i-shell-for-individual-user 22 | -------------------------------------------------------------------------------- /setup-office65-email-apppassword.md: -------------------------------------------------------------------------------- 1 | # How to create an app password in Microsoft O365 using admin portal for outbound email 2 | 3 | ## Problem 4 | Office 365 or M365 now requires sending outbound email messages via SMTP to use an app password. It's not readily apparent how to enable app passwords in your O365 tenant or for an individual user accounts. 5 | 6 | This affects any applications that wants to send or receive email messages via SMTP, POP3 and IMAP via Office 365. 7 | 8 | ## Resolution 9 | - The following YouTube video link illustrates the following: 10 | - How to initially check if you can create an app password for a user. 11 | - How to enable Multifactor Authentication (MFA) in your O365 Tenant. 12 | 13 | Once you have an app password created, your email applications can authenticate using the accounts email address and app password for SMTP, POP3 and IMAP credentials. 14 | 15 | ## Video Link 16 | How to create an app password in Microsoft O365 using admin portal|ERP & Application server||2024 17 | https://www.youtube.com/watch?v=diBOfLxG5Wc 18 | 19 | -------------------------------------------------------------------------------- /tmux-howto.md: -------------------------------------------------------------------------------- 1 | # How to use tmux to manage SSH terminal sessions 2 | 3 | ## Start a tmux session 4 | 5 | Type ```tmux``` and press enter to start a tmux session, 6 | 7 | Run the command or bash script you want to be long running. 8 | 9 | Press ```Ctrl-B``` then press ```D ``` to disconnect from session 10 | 11 | ## List active sessions 12 | ```tmux ls``` 13 | 14 | ## Attach to select tmux session 15 | ```tmux attach -t 0``` 16 | 17 | ## Create a named tmux session 18 | tmux new -s Session1 19 | 20 | ## Links 21 | tmux cheat sheet 22 | https://tmuxcheatsheet.com/ 23 | 24 | Beginners guide to tmux 25 | https://www.redhat.com/en/blog/introduction-tmux-linux 26 | 27 | -------------------------------------------------------------------------------- /tn5250keys.md: -------------------------------------------------------------------------------- 1 | # Keys for tn5250 2 | https://github.com/luca-vercelli/tn5250 3 | ``` 4 | Inside session, you can type: 5 | 6 | ^H = Left (backspace) 7 | ^R = Resume (if locked) 8 | ^P = Print 9 | ^? = Del 10 | ^M = Enter 11 | 12 | ^E, ^X = delete line? 13 | ^I = new line? (Horizontal Tab) 14 | ^J, ^K, ^L = delete to eol + new line? (Vertical Tab) 15 | 16 | dixit: ^N/^O = toggle character set 17 | 18 | AID codes: 19 | KEY Code 20 | F1 31 21 | F2 32 22 | F3 33 23 | F4 34 24 | F5 35 25 | F6 36 26 | F7 37 27 | F8 38 28 | F9 39 29 | F10 3a 30 | F11 3b 31 | F12 3c 32 | F13 b1 33 | F14 b2 34 | F15 b3 35 | F16 b4 36 | F17 b5 37 | F18 b6 38 | F19 b7 39 | F20 b8 40 | F21 b9 41 | F22 ba 42 | F23 bb 43 | F24 bc 44 | CLEAR bd 45 | ENTER f1 46 | HELP f3 47 | DOWN f4 48 | UP f5 49 | PRINT f6 50 | RBS f8 51 | 52 | Field Exit key = Shift Delete Down-Arrow-Key 53 | ``` 54 | -------------------------------------------------------------------------------- /update-alternatives-ibmi.md: -------------------------------------------------------------------------------- 1 | # Use update-alternatives to update default open source apps 2 | 3 | ## Python version to use 4 | 5 | List available Python versions 6 | ``` 7 | update-alternatives --list python 8 | 9 | /QOpenSys/pkgs/bin/python2.7 10 | /QOpenSys/pkgs/bin/python3.6 11 | /QOpenSys/pkgs/bin/python3.9 12 | ``` 13 | 14 | Set Python 3.9 as default 15 | ``` 16 | update-alternatives --set python /QOpenSys/pkgs/bin/python3.9 17 | ``` 18 | 19 | ## Node version to use 20 | 21 | List available node versions 22 | ``` 23 | update-alternatives --list node 24 | 25 | /QOpenSys/pkgs/bin/node 26 | /QOpenSys/pkgs/lib/nodejs10/bin/node 27 | /QOpenSys/pkgs/lib/nodejs12/bin/node 28 | /QOpenSys/pkgs/lib/nodejs14/bin/node 29 | /QOpenSys/pkgs/lib/nodejs16/bin/node 30 | /QOpenSys/pkgs/lib/nodejs18/bin/node 31 | ``` 32 | 33 | Set Node 18 as default 34 | ``` 35 | update-alternatives --set node /QOpenSys/pkgs/lib/nodejs18/bin/node 36 | ``` 37 | -------------------------------------------------------------------------------- /use_ssh_keys_ibmi.md: -------------------------------------------------------------------------------- 1 | # Use SSH Keys to Stop User Password Access 2 | This is a nice article from Andy Youens. Check out the link below 3 | https://powerwire.eu/use-ssh-keys-to-stop-user-password-access/ 4 | 5 | Also the script is listed below. 6 | 7 | sshsetup.sh 8 | ``` 9 | #!/QOpenSys/pkgs/bin/bash 10 | 11 | # FormaServe IBM i Training 12 | 13 | # For full disclaimer see https://www.formaserve.co.uk/examples.php 14 | 15 | # © - FormaServe Systems Ltd. 1990 - 2024 16 | 17 | # www.FormaServe.co.uk 18 | # powerwire.eu 19 | 20 | # Buy me a coffee if this works! - https://Ko-fi.com/andyyouens 21 | 22 | echo " " 23 | echo "Correcting SSH user directories & authorities" 24 | echo " " 25 | 26 | # prompt the user for a user name 27 | read -p "Enter a user name: " -r user 28 | 29 | # Check if string is empty using -z. 30 | if [[ -z "$user" ]]; then 31 | printf '%s\n' "No user entered!" 32 | exit 1 33 | else 34 | # If user is not empty show what the user typed in and run ls -l 35 | printf "Resetting Directories & Files for %s" "$user" 36 | 37 | # change the current working directory to the user's home directory 38 | cd /home/$user 39 | 40 | # is there an .ssh directory, if not create 41 | if ! test -d /home/$user/.ssh; then 42 | echo ".ssh directory doesnt exist - creating it" 43 | mkdir /home/$user/.ssh 44 | fi 45 | 46 | # is there an authorized_keys file, if not create 47 | if ! test -f /home/$user/.ssh/authorized_keys; then 48 | echo ".ssh/authorized_keys file doesnt exist - creating it" 49 | touch /home/$user/.ssh/authorized_keys 50 | fi 51 | 52 | # change the owner and group of the home directory to the user name 53 | chown $user /home/$user 54 | chmod 755 /home/$user 55 | chown $user /home/$user 56 | chmod 700 /home/$user/.ssh/ 57 | chmod 600 /home/$user/.ssh/authorized_keys 58 | 59 | echo ' ' 60 | echo 'Finished setting up user directories & authorities' 61 | echo ' ' 62 | 63 | fi 64 | ``` 65 | -------------------------------------------------------------------------------- /usefulmacapps.md: -------------------------------------------------------------------------------- 1 | # Here is a list of useful Mac Apps For Development 2 | ``` 3 | VS Code - Editor 4 | Geany - Editor 5 | IBM i ACS - IBM i Access 6 | Filezilla - FTP Client 7 | Flux - Screen dimming 8 | Microsoft Remote Desktop Client 9 | Cisco Anyconnect VPN Client 10 | MS Office 11 | LibreOffice 12 | Slack 13 | Webex 14 | Microsoft Visual Studio 15 | XCode 16 | ``` 17 | -------------------------------------------------------------------------------- /windows/batfile-timestamps.md: -------------------------------------------------------------------------------- 1 | # Setting timestamp fields in a Windows .BAT file 2 | Setting timestamps in a Windows batch file seems to be painful. I found the following example code that should work in your .BAT files. 3 | 4 | After creating this script you should have variables available to use for: 5 | ```timestamp``` - yyyymmdd_hhmmss 6 | ```year``` - yyyy 7 | ```month``` - mm 8 | ```day``` - dd 9 | ```hour``` - hh 10 | ```minute``` - mm 11 | ```second``` - ss 12 | 13 | ``` 14 | REM https://www.jamesparker.dev/how-do-i-get-the-current-date-and-time-in-a-batch-file/ 15 | REM @echo off 16 | for /f "delims=" %%a in ('wmic os get localdatetime ^| find "."') do set datetime=%%a 17 | set year=%datetime:~0,4% 18 | set month=%datetime:~4,2% 19 | set day=%datetime:~6,2% 20 | set hour=%datetime:~8,2% 21 | set minute=%datetime:~10,2% 22 | set second=%datetime:~12,2% 23 | set timestamp=%year%%month%%day%_%hour%%minute%%second% 24 | REM Display the timestamp value for our demo 25 | echo %timestamp% 26 | ``` 27 | Example usage to create an output file with a timestamped name: 28 | ``` 29 | for /f "delims=" %%a in ('wmic os get localdatetime ^| find "."') do set datetime=%%a 30 | set year=%datetime:~0,4% 31 | set month=%datetime:~4,2% 32 | set day=%datetime:~6,2% 33 | set hour=%datetime:~8,2% 34 | set minute=%datetime:~10,2% 35 | set second=%datetime:~12,2% 36 | set timestamp=%year%%month%%day%_%hour%%minute%%second% 37 | REM Set output text file 38 | set outputfilename = c:\temp\outputfile_%timestamp%.txt 39 | REM Display the timestamped file name value for our demo 40 | echo %outputfilename% 41 | ``` 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /writelogmessagefromstoredprocedure.md: -------------------------------------------------------------------------------- 1 | # Write log message to selected message queue from stored procedure 2 | 3 | This sample creates a CL command, CL program and a stored procedure to test with from ACS or STRSQL. 4 | 5 | Messages are written by default to message queue: QSYS/QSYSOPR, but can be overridden or the CL program can call an RPG program or any other code. 6 | 7 | ## CL Command - OPPGMMSG.CMD 8 | ``` 9 | * CRTCMD CMD(QGPL/OPPGMMSG) */ 10 | * PGM(QGPL/OPPGMMSGC) */ 11 | * SRCFILE(RJSDEVMB/SRCOPNUTIL) */ 12 | * SRCMBR(OPPGMMSG) */ 13 | * PRDLIB(QGPL) */ 14 | * REPLACE(*YES) */ 15 | CMD PROMPT('Send Program Message') 16 | PARM KWD(MSGDTA) TYPE(*CHAR) LEN(255) MIN(1) + 17 | CASE(*MIXED) PROMPT('Message date') 18 | PARM KWD(MSGQ) TYPE(*CHAR) LEN(10) DFT(QSYSOPR) + 19 | CASE(*MIXED) PROMPT('Message queue') 20 | PARM KWD(MSGQLIB) TYPE(*CHAR) LEN(10) + 21 | DFT(QSYS) CASE(*MIXED) PROMPT('Message + 22 | queue') 23 | ``` 24 | 25 | ## CL Command Processing Program OPPGMMSGC.CLP 26 | ``` 27 | PGM PARM(&MSGDTA &MSGQ &MSGQLIB) 28 | 29 | DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(255) 30 | DCL VAR(&MSGQ) TYPE(*CHAR) LEN(10) 31 | DCL VAR(&MSGQLIB) TYPE(*CHAR) LEN(10) 32 | 33 | MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERRORS)) 34 | 35 | /* SEND PROGRAM MESSAGE */ 36 | SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA(&MSGDTA) + 37 | TOPGMQ(*SAME) TOMSGQ(&MSGQLIB/&MSGQ) + 38 | MSGTYPE(*INFO) 39 | RETURN 40 | 41 | /* HANDLE SEND MESSAGE ERRORS */ 42 | ERRORS: 43 | SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Errors + 44 | running OPPGMMSG') TOMSGQ(*SYSOPR) + 45 | MSGTYPE(*INFO) 46 | /* DISPLAY JOBLOG ON ANY FAILURE */ 47 | DSPJOBLOG OUTPUT(*PRINT) 48 | MONMSG MSGID(CPF0000) 49 | 50 | ENDPGM 51 | ``` 52 | 53 | ## Sample Stored Procedure SpOpPgmMsg that uses OPPGMMSG CL command 54 | The stored procedure writes to message queue: QSYS/QSYSOPR 55 | ``` 56 | CREATE OR REPLACE PROCEDURE 57 | QGPL.SpOpPgmMsg 58 | ( 59 | ) 60 | LANGUAGE SQL 61 | MODIFIES SQL DATA 62 | BEGIN 63 | 64 | DECLARE msgvar varchar(255); 65 | 66 | set msgvar = 'I am a test message'; 67 | 68 | Call QSYS2.QCMDEXC('RJSDEVMB/OPPGMMSG MSGDTA('''|| msgvar ||''') MSGQ(QSYSOPR) MSGQLIB(QSYS)'); 69 | 70 | END 71 | ; 72 | ``` 73 | 74 | ## Call Sample Stored Procedure SpOpPgmMsg 75 | ``` 76 | call QGPL.SpOpPgmMsg(); 77 | ``` 78 | 79 | ## Sending Message Back via Output Parameter from Stored Procedure 80 | This example allows you to output any return parameters in the ACS message list at the bottom of the Run SQL Statements screen. 81 | 82 | ``` 83 | --Sample Stored Procedure 84 | CREATE OR REPLACE PROCEDURE 85 | QGPL.SpOpPgmMsg 86 | ( 87 | OUT msgvar varchar(255) 88 | ) 89 | LANGUAGE SQL 90 | MODIFIES SQL DATA 91 | BEGIN 92 | 93 | --DECLARE msgvar varchar(255); 94 | 95 | set msgvar = 'I am a test message'; 96 | 97 | END 98 | ; 99 | ``` 100 | 101 | ## Call sproc with ? parameter marker/placeholder for output parameter. This will get ACS to output to its message window. 102 | ``` 103 | call QGPL/SpOpPgmMsg(?); 104 | ``` 105 | 106 | ## This is what ACS shows after call to stored procedure 107 | Return Code = 0 108 | **Output Parameter #1 (MSGVAR) = I am a test message** 109 | Statement ran successfully (152 ms) 110 | --------------------------------------------------------------------------------