Query IBM i Db2 databases over SSH — no ibm_db driver required
Project description
db2ssh
Query IBM i Db2 databases over SSH — no ibm_db driver required.
Why
The ibm_db Python driver bundles IBM's proprietary ODBC/CLI libraries, which creates licensing friction, installation headaches, and platform compatibility issues. This project takes a different approach: connect to the IBM i via SSH and use its built-in db2 command-line tool.
Requirements
- Python 3.7+
- SSH access to the target IBM i system
Installation
pip install db2ssh
Usage
DB-API 2.0 Driver
Drop-in replacement pattern for code that expects a PEP 249 database interface:
from db2ssh import connect
conn = connect(host="your-ibm-i.example.com", user="myuser", password="mypass")
cur = conn.cursor()
cur.execute("SELECT TABLE_NAME, TABLE_TYPE FROM QSYS2.SYSTABLES WHERE TABLE_TYPE = ? FETCH FIRST 10 ROWS ONLY", ['L'])
for row in cur.fetchall():
print(row)
conn.close()
With context manager:
with connect(host="your-ibm-i.example.com", user="myuser", password="mypass") as conn:
cur = conn.cursor()
cur.execute("SELECT COUNT(*) FROM QSYS2.SYSTABLES")
print(cur.fetchone())
With SSH key:
conn = connect(host="your-ibm-i.example.com", user="myuser", key_filename="~/.ssh/id_rsa")
Without password or key, paramiko will try SSH agent and default keys (~/.ssh/id_rsa, etc.):
conn = connect(host="your-ibm-i.example.com", user="myuser")
CLI Tool
After pip install db2ssh, the db2ssh command is available:
# Password auth
db2ssh --host your-ibm-i.example.com --user myuser --password mypass \
--query "SELECT * FROM QSYS2.SYSTABLES FETCH FIRST 5 ROWS ONLY"
# Key-based auth
db2ssh --host your-ibm-i.example.com --user myuser \
--key-file ~/.ssh/id_rsa \
--query "SELECT * FROM QSYS2.SYSTABLES FETCH FIRST 5 ROWS ONLY"
# From a SQL file
db2ssh --host your-ibm-i.example.com --user myuser --password mypass \
--file queries.sql
# Save output to file
db2ssh --host your-ibm-i.example.com --user myuser --password mypass \
--query "SELECT * FROM QSYS2.SYSTABLES" --output results.txt
# Password via environment variable
export DB2_PASSWORD=mypass
db2ssh --host your-ibm-i.example.com --user myuser \
--query "SELECT CURRENT_DATE FROM SYSIBM.SYSDUMMY1"
How It Works
- Opens an SSH connection to the IBM i using paramiko
- Writes the SQL statement to a temporary file on the remote system
- Executes the query via
qsh -c "db2 -f <file>" - Parses the fixed-width columnar output into structured results
- Cleans up the remote temp file
No software needs to be installed on the IBM i beyond its default SSH server and the built-in db2 command.
DB-API 2.0 Compliance
| Feature | Status |
|---|---|
connect() |
Implemented |
Connection.cursor() |
Implemented |
Cursor.execute() |
Implemented |
Cursor.executemany() |
Implemented |
Cursor.fetchone() |
Implemented |
Cursor.fetchmany() |
Implemented |
Cursor.fetchall() |
Implemented |
| Iterator protocol | Implemented |
| Context manager | Implemented |
? (qmark) parameter style |
Implemented |
| Error hierarchy | Implemented |
commit() |
No-op (IBM i autocommit) |
rollback() |
Raises NotSupportedError |
Error Handling
All errors from the IBM i are raised as DB-API 2.0 exceptions:
from db2ssh import connect, ProgrammingError, OperationalError
try:
conn = connect(host="bad-host", user="user", password="pass")
except OperationalError as e:
print(f"Connection failed: {e}")
try:
cur.execute("SELECT * FROM NONEXISTENT.TABLE")
except ProgrammingError as e:
print(f"Query failed: {e}")
Security Notes
- Authentication: Supports password auth and SSH key-based auth. Key auth is recommended for production — use
--key-fileor passkey_filenametoconnect(). If no password or key is specified, paramiko will try your SSH agent and default keys (~/.ssh/id_rsa, etc.). - Passwords: Use the
DB2_PASSWORDenvironment variable or interactive prompt rather than passing passwords on the command line. - Host key verification: The default configuration auto-accepts unknown SSH host keys (
AutoAddPolicy). For production use, consider implementing strict host key checking. - Temp files: A uniquely-named SQL file (
/tmp/.db2ssh_<uuid>.sql) is written to the IBM i during each query execution and deleted immediately after. The UUID-based name prevents collision between concurrent executions and eliminates symlink-based TOCTOU attacks.
Limitations
- Result sets only: DDL/DML statements that don't return rows will execute but won't report affected row counts accurately.
NULLliteral: BareSELECT NULLmay not work on some IBM i versions. UseCAST(NULL AS <type>)instead.- No transactions:
commit()is a no-op,rollback()raisesNotSupportedError. - Single-threaded: Each
Connectionobject holds one SSH session. Share across threads at the module level only (threadsafety=1). - No SSL/TLS: SSH transport is encrypted, but the db2 connection from the IBM i to its own database is local.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file db2ssh-1.0.0.tar.gz.
File metadata
- Download URL: db2ssh-1.0.0.tar.gz
- Upload date:
- Size: 10.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
799485348123572862af23a73fdefa635db2a571a52ca8099ea5dfe7b9859f29
|
|
| MD5 |
c481a88daca9b716ad3129571c772b01
|
|
| BLAKE2b-256 |
b79dce4aafd2f58067e761f02114fccac331dafee9ff04f492562d6d97b58bcc
|
Provenance
The following attestation bundles were made for db2ssh-1.0.0.tar.gz:
Publisher:
python-publish.yml on dtg01100/db2ssh
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
db2ssh-1.0.0.tar.gz -
Subject digest:
799485348123572862af23a73fdefa635db2a571a52ca8099ea5dfe7b9859f29 - Sigstore transparency entry: 1186489215
- Sigstore integration time:
-
Permalink:
dtg01100/db2ssh@485db26e41b35f4c2ee1dd17a8ce98d1caec1a1a -
Branch / Tag:
refs/tags/1.0_release - Owner: https://github.com/dtg01100
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@485db26e41b35f4c2ee1dd17a8ce98d1caec1a1a -
Trigger Event:
release
-
Statement type:
File details
Details for the file db2ssh-1.0.0-py3-none-any.whl.
File metadata
- Download URL: db2ssh-1.0.0-py3-none-any.whl
- Upload date:
- Size: 8.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c9fc70e8b0fb19947decefec689c40f906c3bef03d40d6c4e5d7797842bc6172
|
|
| MD5 |
cabc39e5a13beec3cb95b09711c50c34
|
|
| BLAKE2b-256 |
1432372328349d3f32a5fc95100162167a15f067dedc209b89310ea39d1b1677
|
Provenance
The following attestation bundles were made for db2ssh-1.0.0-py3-none-any.whl:
Publisher:
python-publish.yml on dtg01100/db2ssh
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
db2ssh-1.0.0-py3-none-any.whl -
Subject digest:
c9fc70e8b0fb19947decefec689c40f906c3bef03d40d6c4e5d7797842bc6172 - Sigstore transparency entry: 1186489220
- Sigstore integration time:
-
Permalink:
dtg01100/db2ssh@485db26e41b35f4c2ee1dd17a8ce98d1caec1a1a -
Branch / Tag:
refs/tags/1.0_release - Owner: https://github.com/dtg01100
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@485db26e41b35f4c2ee1dd17a8ce98d1caec1a1a -
Trigger Event:
release
-
Statement type: