#!bin/bash
I have the same exact problem for commands like that. I tend to make a little bash script and put it in my home dir bin folder or make an alias for them. Then I only have to remember one command like start-dev or something. That plus ctrl-r for searching history are great.
November 7, 2026 at 3:55 PM
#!/usr/bin/env bash

sudo apt install rust-analyzer
sudo apt install rust
sudo apt install kate
rustup docs --book
kate
exit
November 7, 2026 at 8:18 AM
The bin isn't so bad it is a quiet place to reflect on ones flawed or non existent knowledge! 🤣🤣🙃👍 After a moment of contemplation. It becomes time to correct the problem... when possible and bash onward with great vigor!!👍👍🍻
November 7, 2026 at 9:36 AM
¿Shell sin TTY que se muere con Ctrl+C? Arréglala:

python3 -c 'import pty;pty.spawn("/bin/bash")'
Ctrl+Z
stty raw -echo; fg
export TERM=xterm

#pentesting #HackTheBox
November 4, 2026 at 2:56 PM
do you mean the # !/bin/bash (remove the space didn't want to hashtag it lol) at the top of the script?
November 3, 2026 at 2:37 PM
AI Report
#!/usr/bin/env bash set -Eeuo pipefail ############################################################################### # AEROSPIKE GCS BACKUP ARCHIVAL # # - Inclusive date range # - Root and DRBackupData folder formats # - Full and hourly backup folders # - Prefix-based GCS listing only # - Manifest sorting and complete node sequence validation # - Sequential object archival # - Per-object start time, completion time and duration # - 3 attempts per object, 30 seconds between retries # - 60-minute archival window followed by 1-minute pause # - Dry-run enabled by default # - Incremental report generation # - Local flock to prevent overlapping execution on the same host ############################################################################### ############################ # CONFIGURATION ############################ START_DATE="${START_DATE:-}" END_DATE="${END_DATE:-}" BUCKET_NAME="${BUCKET_NAME:-mbbaero-gcp-mumbai-cual-cluster-backup}" DRY_RUN="${DRY_RUN:-true}" TARGET_STORAGE_CLASS="${TARGET_STORAGE_CLASS:-ARCHIVE}" ARCHIVE_RUN_MINUTES="${ARCHIVE_RUN_MINUTES:-60}" ARCHIVE_SLEEP_MINUTES="${ARCHIVE_SLEEP_MINUTES:-1}" MAX_RETRIES="${MAX_RETRIES:-3}" RETRY_SLEEP_SECONDS="${RETRY_SLEEP_SECONDS:-30}" REPORT_DIR="${REPORT_DIR:-/tmp/aerospike_archive_mb}" LOCK_FILE="${LOCK_FILE:-/tmp/aerospike_archive_mb.lock}" ARCHIVE_RUN_SECONDS=$((ARCHIVE_RUN_MINUTES * 60)) ARCHIVE_SLEEP_SECONDS=$((ARCHIVE_SLEEP_MINUTES * 60)) ############################ # GLOBAL COUNTERS ############################ TOTAL_FOLDERS=0 FOUND_FOLDERS=0 NOT_FOUND_FOLDERS=0 LIST_ERROR_FOLDERS=0 INVALID_SEQUENCE_FOLDERS=0 TOTAL_OBJECTS=0 ARCHIVED_OBJECTS=0 DRY_RUN_OBJECTS=0 FAILED_OBJECTS=0 OVERALL_ERRORS=0 ############################ # INITIALIZATION ############################ mkdir -p "$REPORT_DIR" TIMESTAMP="$(date '+%Y%m%d-%H%M%S')" REPORT_FILE="${REPORT_DIR}/archival_report_${TIMESTAMP}.log" if [[ -e "$REPORT_FILE" ]]; then REPORT_FILE="${REPORT_DIR}/archival_report_${TIMESTAMP}_$$.log" fi TEMP_DIR="$(mktemp -d "${REPORT_DIR}/work.XXXXXX")" cleanup() { rm -rf "$TEMP_DIR" } trap cleanup EXIT write_report() { local message="$1" printf '%s\n' "$message" | tee -a "$REPORT_FILE" } ############################ # REPORT HEADER ############################ write_report "======================================================================" write_report " AEROSPIKE GCS BACKUP ARCHIVAL REPORT" write_report "======================================================================" write_report "Execution Time : $(date '+%Y-%m-%d %H:%M:%S %Z')" write_report "Start Date : ${START_DATE:-NOT PROVIDED}" write_report "End Date : ${END_DATE:-NOT PROVIDED}" write_report "Bucket : ${BUCKET_NAME}" write_report "Target Storage Class : ${TARGET_STORAGE_CLASS}" write_report "Dry Run : ${DRY_RUN}" write_report "Archive Run Window : ${ARCHIVE_RUN_MINUTES} minutes" write_report "Archive Pause : ${ARCHIVE_SLEEP_MINUTES} minute(s)" write_report "Maximum Retries : ${MAX_RETRIES}" write_report "Retry Delay : ${RETRY_SLEEP_SECONDS} seconds" write_report "Execution Mode : Sequential" write_report "Report File : ${REPORT_FILE}" write_report "======================================================================" write_report "" write_report "FOLDER FORMATS:" write_report " mbrw-full-DATE/" write_report " mbrw-incremental-DATE-HH/" write_report " mbrw-cache-full-DATE-HH/" write_report " mbrw-cache-incremental-DATE-HH/" write_report " DRBackupData/mbrw-full-DATE/" write_report " DRBackupData/mbrw-incremental-DATE-HH/" write_report " DRBackupData/mbrw-cache-full-DATE-HH/" write_report " DRBackupData/mbrw-cache-incremental-DATE-HH/" write_report "" write_report "DATE = YYYY-MM-DD; HH = 00 through 23" write_report "======================================================================" write_report "" ############################ # LOCK ############################ exec 9>"$LOCK_FILE" if ! flock -n 9; then write_report "[ERROR] Another archival execution is already running on this host." exit 1 fi ############################ # INPUT VALIDATION ############################ fail() { write_report "[ERROR] $1" exit 1 } validate_date() { local input_date="$1" local normalized [[ "$input_date" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] || return 1 normalized="$(date -d "$input_date" '+%F' 2>/dev/null)" || return 1 [[ "$normalized" == "$input_date" ]] } [[ -n "$START_DATE" ]] || fail "START_DATE is mandatory." [[ -n "$END_DATE" ]] || fail "END_DATE is mandatory." validate_date "$START_DATE" || fail "Invalid START_DATE: $START_DATE" validate_date "$END_DATE" || fail "Invalid END_DATE: $END_DATE" [[ "$START_DATE" > "$END_DATE" ]] && fail "START_DATE cannot be after END_DATE." if [[ ! "$BUCKET_NAME" =~ ^[a-z0-9][a-z0-9._-]*[a-z0-9]$ ]] || (( ${#BUCKET_NAME} < 3 || ${#BUCKET_NAME} > 63 )); then fail "Invalid bucket name: $BUCKET_NAME" fi if [[ "$DRY_RUN" != "true" && "$DRY_RUN" != "false" ]]; then fail "DRY_RUN must be true or false." fi if [[ ! "$TARGET_STORAGE_CLASS" =~ ^(ARCHIVE|COLDLINE|NEARLINE|STANDARD)$ ]]; then fail "Unsupported storage class: $TARGET_STORAGE_CLASS" fi for value in "$ARCHIVE_RUN_MINUTES" "$ARCHIVE_SLEEP_MINUTES" \ "$MAX_RETRIES" "$RETRY_SLEEP_SECONDS"; do [[ "$value" =~ ^[0-9]+$ ]] || fail "Configuration values must be integers." done (( ARCHIVE_RUN_MINUTES > 0 )) || fail "ARCHIVE_RUN_MINUTES must be greater than zero." (( MAX_RETRIES > 0 )) || fail "MAX_RETRIES must be greater than zero." command -v gsutil >/dev/null 2>&1 || fail "gsutil is not installed." command -v flock >/dev/null 2>&1 || fail "flock is not installed." command -v sort >/dev/null 2>&1 || fail "sort is not installed." command -v seq >/dev/null 2>&1 || fail "seq is not installed." ############################ # GLOBAL THROTTLING ############################ ARCHIVE_CYCLE_START="$(date +%s)" wait_for_archive_window() { local now local elapsed [[ "$DRY_RUN" == "true" ]] && return 0 now="$(date +%s)" elapsed=$((now - ARCHIVE_CYCLE_START)) if (( elapsed >= ARCHIVE_RUN_SECONDS )); then write_report "" write_report "======================================================================" write_report "[THROTTLE] ARCHIVAL WINDOW REACHED" write_report "[THROTTLE] Pausing for ${ARCHIVE_SLEEP_MINUTES} minute(s)." write_report "======================================================================" sleep "$ARCHIVE_SLEEP_SECONDS" ARCHIVE_CYCLE_START="$(date +%s)" write_report "[THROTTLE] Resuming archival at $(date '+%Y-%m-%d %H:%M:%S %Z')." write_report "" fi } ############################ # NODE SEQUENCE VALIDATION ############################ validate_node_sequence() { local manifest="$1" local node_file="$2" local object_count local node_count local previous local current local i : > "$node_file" sed -nE 's/.*_node_([0-9]+)\.asb$/\1/p' "$manifest" | sort -n > "$node_file" object_count="$(wc -l < "$manifest" | tr -d ' ')" node_count="$(wc -l < "$node_file" | tr -d ' ')" if (( object_count == 0 || object_count != node_count )); then write_report "[VALIDATION] FAILED: Unexpected object filename format." return 1 fi mapfile -t node_ids < "$node_file" for ((i = 1; i < ${#node_ids[@]}; i++)); do previous=$((10#${node_ids[$((i - 1))]})) current=$((10#${node_ids[$i]})) if (( current == previous )); then write_report "[VALIDATION] FAILED: Duplicate node ID ${node_ids[$i]}." return 1 fi if (( current != previous + 1 )); then write_report "[VALIDATION] FAILED: Node sequence gap between ${node_ids[$((i - 1))]} and ${node_ids[$i]}." return 1 fi done write_report "[VALIDATION] PASSED" write_report "[VALIDATION] Node Count : ${node_count}" write_report "[VALIDATION] First Node : ${node_ids[0]}" write_report "[VALIDATION] Last Node : ${node_ids[${#node_ids[@]}-1]}" return 0 } ############################ # PROCESS ONE FOLDER ############################ process_folder() { local folder="$1" local backup_type="$2" local prefix="gs://${BUCKET_NAME}/${folder}/" local manifest="${TEMP_DIR}/manifest.txt" local node_file="${TEMP_DIR}/nodes.txt" local listing_error="${TEMP_DIR}/listing_error.txt" local object_count local first_object local last_object local folder_archived=0 local folder_dry_run=0 local folder_failed=0 local folder_status local object_number=0 local object local attempt local object_start_epoch local object_end_epoch local object_duration local object_start_time local object_end_time local object_success TOTAL_FOLDERS=$((TOTAL_FOLDERS + 1)) ############################ # FOLDER HEADER ############################ write_report "" write_report "" write_report "######################################################################" write_report " FOLDER: ${folder}/" write_report " TYPE : ${backup_type}" write_report " DATE : ${CURRENT_DATE}" write_report "######################################################################" write_report "[FOLDER STATUS] PROCESSING" write_report "[INFO] GCS Prefix: ${prefix}" write_report "[INFO] Checking folder contents..." : > "$manifest" : > "$listing_error" ############################ # GCS LISTING ############################ if gsutil ls "${prefix}*" > "$manifest" 2> "$listing_error"; then : else if grep -Eqi 'matched no objects|No URLs matched|No objects found' "$listing_error"; then NOT_FOUND_FOLDERS=$((NOT_FOUND_FOLDERS + 1)) write_report "[INFO] Object Count: 0" write_report "[INFO] First Object: N/A" write_report "[INFO] Last Object : N/A" write_report "[FOLDER STATUS] NOT_FOUND" write_report "------------------------------------------------------------------" write_report " FOLDER SUMMARY: ${folder}/" write_report " Total Objects : 0" write_report " Folder Status : NOT_FOUND" write_report "------------------------------------------------------------------" return 0 fi LIST_ERROR_FOLDERS=$((LIST_ERROR_FOLDERS + 1)) OVERALL_ERRORS=$((OVERALL_ERRORS + 1)) write_report "[FOLDER STATUS] LIST_ERROR" write_report "[ERROR] GCS listing failed:" cat "$listing_error" | tee -a "$REPORT_FILE" write_report "------------------------------------------------------------------" write_report " FOLDER SUMMARY: ${folder}/" write_report " Folder Status : LIST_ERROR" write_report "------------------------------------------------------------------" return 0 fi ############################ # MANIFEST ############################ sort -u "$manifest" -o "$manifest" object_count="$(wc -l < "$manifest" | tr -d ' ')" if (( object_count == 0 )); then NOT_FOUND_FOLDERS=$((NOT_FOUND_FOLDERS + 1)) write_report "[FOLDER STATUS] NOT_FOUND" write_report "------------------------------------------------------------------" write_report " FOLDER SUMMARY: ${folder}/" write_report " Total Objects : 0" write_report " Folder Status : NOT_FOUND" write_report "------------------------------------------------------------------" return 0 fi FOUND_FOLDERS=$((FOUND_FOLDERS + 1)) TOTAL_OBJECTS=$((TOTAL_OBJECTS + object_count)) first_object="$(head -n 1 "$manifest")" last_object="$(tail -n 1 "$manifest")" write_report "[INFO] Objects Found : ${object_count}" write_report "[INFO] First Object : ${first_object}" write_report "[INFO] Last Object : ${last_object}" ############################ # NODE VALIDATION ############################ write_report "" write_report "[VALIDATION] Checking node sequence..." if ! validate_node_sequence "$manifest" "$node_file"; then INVALID_SEQUENCE_FOLDERS=$((INVALID_SEQUENCE_FOLDERS + 1)) OVERALL_ERRORS=$((OVERALL_ERRORS + 1)) write_report "[FOLDER STATUS] INVALID_NODE_SEQUENCE" write_report "[INFO] Archival skipped for this folder." write_report "------------------------------------------------------------------" write_report " FOLDER SUMMARY: ${folder}/" write_report " Total Objects : ${object_count}" write_report " Archived : 0" write_report " Failed : 0" write_report " Folder Status : INVALID_NODE_SEQUENCE" write_report "------------------------------------------------------------------" return 0 fi ############################ # OBJECT-BY-OBJECT PROCESSING ############################ while IFS= read -r object; do [[ -n "$object" ]] || continue object_number=$((object_number + 1)) # Check throttle before starting the object timer. wait_for_archive_window object_start_epoch="$(date +%s)" object_start_time="$(date '+%Y-%m-%d %H:%M:%S %Z')" write_report "" write_report "------------------------------------------------------------------" write_report "[PROCESSING ${object_number}/${object_count}]" write_report "Object : ${object}" write_report "Start Time : ${object_start_time}" write_report "------------------------------------------------------------------" ############################ # DRY RUN ############################ if [[ "$DRY_RUN" == "true" ]]; then write_report "[DRY-RUN ${object_number}/${object_count}] Would archive: ${object}" write_report "Status : DRY_RUN_SUCCESS" object_end_epoch="$(date +%s)" object_end_time="$(date '+%Y-%m-%d %H:%M:%S %Z')" object_duration=$((object_end_epoch - object_start_epoch)) write_report "Completion : ${object_end_time}" write_report "Duration : ${object_duration} seconds" folder_dry_run=$((folder_dry_run + 1)) DRY_RUN_OBJECTS=$((DRY_RUN_OBJECTS + 1)) continue fi ############################ # ACTUAL ARCHIVAL WITH RETRIES ############################ object_success=false for ((attempt = 1; attempt <= MAX_RETRIES; attempt++)); do write_report "" write_report "[ATTEMPT ${attempt}/${MAX_RETRIES}]" write_report "[INFO] Target Storage Class: ${TARGET_STORAGE_CLASS}" if gsutil rewrite -s "$TARGET_STORAGE_CLASS" "$object" "$object" \ >> "$REPORT_FILE" 2>&1; then object_success=true write_report "[ATTEMPT ${attempt}/${MAX_RETRIES}] SUCCESS" break else write_report "[ATTEMPT ${attempt}/${MAX_RETRIES}] FAILED" if (( attempt < MAX_RETRIES )); then write_report "[RETRY] Waiting ${RETRY_SLEEP_SECONDS} seconds before retry." sleep "$RETRY_SLEEP_SECONDS" fi fi done ############################ # OBJECT COMPLETION REPORT ############################ object_end_epoch="$(date +%s)" object_end_time="$(date '+%Y-%m-%d %H:%M:%S %Z')" object_duration=$((object_end_epoch - object_start_epoch)) if [[ "$object_success" == "true" ]]; then folder_archived=$((folder_archived + 1)) ARCHIVED_OBJECTS=$((ARCHIVED_OBJECTS + 1)) write_report "Final Status : SUCCESS" else folder_failed=$((folder_failed + 1)) FAILED_OBJECTS=$((FAILED_OBJECTS + 1)) OVERALL_ERRORS=$((OVERALL_ERRORS + 1)) write_report "Final Status : FAILED" write_report "[ERROR] Object failed after ${MAX_RETRIES} attempts." fi write_report "Completion : ${object_end_time}" write_report "Duration : ${object_duration} seconds" done < "$manifest" ############################ # FOLDER SUMMARY ############################ write_report "" write_report "======================================================================" write_report " FOLDER SUMMARY: ${folder}/" write_report "======================================================================" write_report "Total Objects : ${object_count}" write_report "Archived : ${folder_archived}" write_report "Dry Run : ${folder_dry_run}" write_report "Failed : ${folder_failed}" if [[ "$DRY_RUN" == "true" ]]; then folder_status="DRY_RUN_SUCCESS" elif (( folder_failed > 0 )); then folder_status="ARCHIVE_FAILED" else folder_status="ARCHIVED" fi write_report "Folder Status : ${folder_status}" write_report "======================================================================" } ############################ # PROCESS ONE DATE ############################ process_date() { local date_value="$1" local hour CURRENT_DATE="$date_value" write_report "" write_report "" write_report "######################################################################" write_report " DATE PROCESSING: ${CURRENT_DATE}" write_report "######################################################################" # FULL BACKUPS - no hour suffix process_folder "mbrw-full-${CURRENT_DATE}" "FULL" process_folder "DRBackupData/mbrw-full-${CURRENT_DATE}" "DR FULL" # HOURLY BACKUPS - 00 through 23 for hour in $(seq -w 0 23); do process_folder "mbrw-incremental-${CURRENT_DATE}-${hour}" "INCREMENTAL" process_folder "mbrw-cache-full-${CURRENT_DATE}-${hour}" "CACHE FULL" process_folder "mbrw-cache-incremental-${CURRENT_DATE}-${hour}" "CACHE INCREMENTAL" process_folder "DRBackupData/mbrw-incremental-${CURRENT_DATE}-${hour}" "DR INCREMENTAL" process_folder "DRBackupData/mbrw-cache-full-${CURRENT_DATE}-${hour}" "DR CACHE FULL" process_folder "DRBackupData/mbrw-cache-incremental-${CURRENT_DATE}-${hour}" "DR CACHE INCREMENTAL" done } ############################ # MAIN EXECUTION ############################ write_report "[INFO] Starting archival date range processing." CURRENT_DATE="$START_DATE" while [[ "$CURRENT_DATE" < "$END_DATE" || "$CURRENT_DATE" == "$END_DATE" ]]; do process_date "$CURRENT_DATE" CURRENT_DATE="$(date -d "${CURRENT_DATE} + 1 day" '+%F')" done ############################ # FINAL EXECUTION SUMMARY ############################ write_report "" write_report "" write_report "======================================================================" write_report " FINAL ARCHIVAL EXECUTION SUMMARY" write_report "======================================================================" write_report "Execution Completed : $(date '+%Y-%m-%d %H:%M:%S %Z')" write_report "Bucket : ${BUCKET_NAME}" write_report "Date Range : ${START_DATE} to ${END_DATE}" write_report "Target Storage Class: ${TARGET_STORAGE_CLASS}" write_report "Dry Run : ${DRY_RUN}" write_report "" write_report "Total Folders : ${TOTAL_FOLDERS}" write_report "Folders Found : ${FOUND_FOLDERS}" write_report "Folders Not Found : ${NOT_FOUND_FOLDERS}" write_report "Listing Errors : ${LIST_ERROR_FOLDERS}" write_report "Invalid Sequences : ${INVALID_SEQUENCE_FOLDERS}" write_report "" write_report "Total Objects : ${TOTAL_OBJECTS}" write_report "Archived Objects : ${ARCHIVED_OBJECTS}" write_report "Dry Run Objects : ${DRY_RUN_OBJECTS}" write_report "Failed Objects : ${FAILED_OBJECTS}" write_report "" write_report "Overall Errors : ${OVERALL_ERRORS}" write_report "Report File : ${REPORT_FILE}" write_report "======================================================================" if (( OVERALL_ERRORS > 0 )); then write_report "[FINAL STATUS] FAILED - Review the archival report." exit 1 fi write_report "[FINAL STATUS] SUCCESS" exit 0 p --- - name: Aerospike MB Backup Archival hosts: localhost connection: local gather_facts: false vars: archive_script: "{{ playbook_dir }}/../scripts/aerospike_archive_mb.sh" # Default configuration archive_bucket: "{{ bucket_name | default('mbbaero-gcp-mumbai-cual-cluster-backup') }}" archive_dry_run: "{{ dry_run | default(true) }}" archive_storage_class: "{{ target_storage_class | default('ARCHIVE') }}" archive_run_minutes: "{{ archive_run_minutes_override | default(60) }}" archive_sleep_minutes: "{{ archive_sleep_minutes_override | default(1) }}" archive_max_retries: "{{ max_retries | default(3) }}" archive_retry_sleep_seconds: "{{ retry_sleep_seconds | default(30) }}" archive_report_dir: "{{ report_dir | default('/tmp/aerospike_archive_mb') }}" tasks: - name: Validate mandatory date inputs ansible.builtin.assert: that: - start_date is defined - end_date is defined - start_date | string is match('^[0-9]{4}-[0-9]{2}-[0-9]{2}$') - end_date | string is match('^[0-9]{4}-[0-9]{2}-[0-9]{2}$') fail_msg: > Provide start_date and end_date in YYYY-MM-DD format. - name: Validate date range ansible.builtin.assert: that: - start_date <= end_date fail_msg: "start_date cannot be after end_date." - name: Verify archival script exists ansible.builtin.stat: path: "{{ archive_script }}" register: script_status - name: Fail if archival script is missing ansible.builtin.assert: that: - script_status.stat.exists - script_status.stat.isreg fail_msg: "Aerospike archival Bash script not found." - name: Display execution configuration ansible.builtin.debug: msg: - "Bucket: {{ archive_bucket }}" - "Start Date: {{ start_date }}" - "End Date: {{ end_date }}" - "Dry Run: {{ archive_dry_run }}" - "Storage Class: {{ archive_storage_class }}" - "Archive Run Window: {{ archive_run_minutes }} minutes" - "Archive Pause: {{ archive_sleep_minutes }} minutes" - "Maximum Retries: {{ archive_max_retries }}" - "Retry Delay: {{ archive_retry_sleep_seconds }} seconds" - name: Execute Aerospike backup archival ansible.builtin.command: argv: - /bin/bash - "{{ archive_script }}" environment: START_DATE: "{{ start_date }}" END_DATE: "{{ end_date }}" BUCKET_NAME: "{{ archive_bucket }}" DRY_RUN: "{{ archive_dry_run | string | lower }}" TARGET_STORAGE_CLASS: "{{ archive_storage_class }}" ARCHIVE_RUN_MINUTES: "{{ archive_run_minutes }}" ARCHIVE_SLEEP_MINUTES: "{{ archive_sleep_minutes }}" MAX_RETRIES: "{{ archive_max_retries }}" RETRY_SLEEP_SECONDS: "{{ archive_retry_sleep_seconds }}" REPORT_DIR: "{{ archive_report_dir }}" register: archive_result changed_when: archive_result.rc == 0 and not (archive_dry_run | bool) failed_when: false - name: Display archival execution output ansible.builtin.debug: var: archive_result.stdout_lines - name: Display archival error output ansible.builtin.debug: var: archive_result.stderr_lines when: archive_result.stderr | default('') | length > 0 - name: Fail AWX job if archival execution failed ansible.builtin.assert: that: - archive_result.rc == 0 fail_msg: > Aerospike backup archival failed. Review the AWX execution output and archival report. - name: Display final execution details ansible.builtin.debug: msg: - "Archival execution completed successfully." - "Bucket: {{ archive_bucket }}" - "Date Range: {{ start_date }} to {{ end_date }}" - "Dry Run: {{ archive_dry_run }}" - "Report Directory: {{ archive_report_dir }}" v dry_run: true target_storage_class: ARCHIVE archive_run_minutes_override: 60 archive_sleep_minutes_override: 1 max_retries: 3 retry_sleep_seconds: 30 report_dir: /tmp/aerospike_archive_mb START_DATE="2026-11-01" \ END_DATE="2026-11-03" \ DRY_RUN=true \ bash scripts/aerospike_archive_mb.sh bash -n scripts/aerospike_archive_mb.sh
dev.to
November 5, 2026 at 10:34 AM
Claude Code sandbox on and every Bash command fails with "Exit code 126"? On Linux with zsh, the reporter says SHELL=/bin/bash claude made the sandbox work again.

Plus: Docker Desktop (WSL2) refusing Bash, and 6–8 GB OOM.

edtrackai.github.io/blog/claude-code-sandbox-settings-exit-code-126
October 31, 2026 at 8:06 AM
So it runs on vanilla Wine 11.21 actually

The development suite works too. But for debugging, you need to set SHELL=/bin/sh in Wine, as if it tries to run bash, it fails, as Linux vars bleed into that Cygwin environment
The Palm OS Cobalt simulator running on Wine Staging. A lot of it is native Win32, because the PalmSource did not make an ARM emulator.

The fact that it is running is impressive
November 3, 2026 at 10:44 PM
让 Claude Code 连数据库的注意下: curl 把密码从 ps 里藏了,外面那层 shell 没藏
我自己机器上查了一下,253 个 Claude Code 会话记录里,有 16 个出现过 `mysql -p 密码`、`curl -u user:pass` 这类写法。顺手看了下 AI 跑这种命令时 ps 里是什么样,发现比我以为的多了一层。 今天在 Mac 上复现( Claude Code 2.1.317 ):让它跑一条带假密码的 curl ,另起一个进程抓 ps: 54958 64286 /bin/zsh -c source ~/.claude/shell-snapshots/… && eval 'curl -s -m 8 -u demo:FAKEPASS123 http://10.255.255.1/' … 54959 54958 curl -s -m 8 -u http://10.255.255.1/ (中间加载环境的一大段我删了) 下面那行是 curl 自己,密码那几位已经被它抹成空格了,curl 确实有做这件事。上面那行是 Claude Code 起的 zsh ,整条命令连密码都在,curl 跑多久它就挂多久。 有个细节:你自己 `bash -c 'curl ...'` 只跑一条命令的话,bash 会直接 exec 成 curl ,看不到这一层。Claude Code 是把命令包在 `source 快照 && ... && eval '你的命令'` 里,是复合命令,shell 得留着等它跑完,这份就一直在。 除了 ps ,命令还会原样写进 `~/.claude/projects/` 下面的会话记录( jsonl )。 服务器上更要留意。Linux 默认挂载参数下,proc(5) 写的是 "everybody may access all /proc/pid directories",同机其他用户能看到你的命令行。环境变量反而不一样,读 `/proc/pid/environ` 要过 ptrace 的权限检查。共用开发机、跳板机的可以注意下。 各家文档其实早就劝过: * MySQL:命令行里 `-p 密码` 方便但不安全;`MYSQL_PWD` 被写成"极不安全",8.4 已经标了弃用 * PostgreSQL:不推荐 `PGPASSWORD`,让用 `~/.pgpass`,权限比 0600 宽它直接不读 * curl:`-u` 能藏就藏,但手册自己也说这不够防同机其他用户 * redis-cli 带 `-a` 会自己打一行警告 说的都是一件事:别放参数里,放权限 600 的配置文件。 自查,只数数量,不打印内容: P='(mysql|mysqldump|mysqladmin)[^"\\]* -p[^ "\\]|redis-cli[^"\\]* -a [^ "\\]|curl[^"\\]* (-u|--user) [^ "\\:]+:[^ "\\]|PGPASSWORD=[^ $"\\]' # 有命中的 Claude Code 会话数 grep -lE -- "$P" ~/.claude/projects/*/*.jsonl 2>/dev/null | wc -l # shell 历史里的行数 cat ~/.zsh_history ~/.bash_history 2>/dev/null | grep -acE -- "$P" 我这边是会话 16 个、shell 历史 8 行。正则比较粗,会漏也会误报,不是 0 就值得翻一下。 不装任何东西的改法: 1. `~/.my.cnf`、`~/.pgpass` 各自配好,chmod 600 2. `CLAUDE.md` / `AGENTS.md` 里加一句:密钥不要出现在命令参数里,用客户端自己的配置文件 3. 已经进过会话的密码直接换掉。删 jsonl 没用,那段已经发给模型了 我现在用的是自己做的小密盾,让 AI 跑 `rootkey run "订单库" --env-var PGPASSWORD -- psql ...`,值只进那个子进程的环境变量,ps 和会话记录里只有条目名。也不是银弹:MySQL 官方更推荐的还是 600 的配置文件;同一个用户下跑的恶意程序照样能读你的环境变量和文件。 大家让 AI 连库现在是怎么给密码的?
www.v2ex.com
November 3, 2026 at 12:51 PM
#!/bin/bash

DATE=$(date +"%Y-%m-%d %H:%M:%S")

git add .
git commit -m "$DATE"
git push

I've got cool names though Pangeneses, Iridium, etc.
October 27, 2026 at 5:33 PM
Netdata is an exceptional real-time performance and health monitoring tool. While its automated installation and update scripts handle most things out of the box, there are times when you want precise control over specific components - like keeping your web dashboard UI up to date.
Automating Netdata Dashboard Updates: A Custom Bash Script for Seamless UI Upgrades
To solve this, I put together a robust, production-ready Bash script that automates checking, downloading, backing up, and updating the Netdata web dashboard directly from Netdata Cloud's official tarball release. The Script Here is the complete script. #!/usr/bin/env bash set -e # Configuration WEB_DIR="/usr/local/share/netdata/web" [ ! -d "$WEB_DIR" ] && [ -d "/usr/share/netdata/web" ] && WEB_DIR="/usr/share/netdata/web" DASHBOARD_URL="https://app.netdata.cloud/agent.tar.gz" TMP_DIR="/tmp/netdata_dashboard_update" # 1. Check root privileges if [ "${EUID:-$(id -u)}" -ne 0 ]; then echo "Error: This script must be run as root (sudo)." exit 1 fi # 2. Check required tools for cmd in curl tar sed sort tail find; do if ! command -v $cmd &> /dev/null; then echo "Error: Tool '$cmd' is not installed." exit 1 fi done # 3. Get installed dashboard version get_installed_version() { ls "${WEB_DIR}/v3"/allFiles.*.json 2>/dev/null | \ sed 's|.*/allFiles\.\(.*\)\.json|\1|' | \ sort -V | tail -n 1 } # 4. Get remote dashboard version directly from the archive get_remote_version() { curl -sL "${DASHBOARD_URL}" | \ tar -tzf - 2>/dev/null | \ grep 'allFiles\..*\.json' | \ sed -n 's/.*allFiles\.\(.*\)\.json/\1/p' | \ sort -V | tail -n 1 } CURRENT_VERSION=$(get_installed_version) [ -z "$CURRENT_VERSION" ] && CURRENT_VERSION="none" echo "--- Checking dashboard version ---" echo "Current installed version: $CURRENT_VERSION" echo "Fetching remote version from Netdata Cloud..." REMOTE_VERSION=$(get_remote_version) if [ -z "$REMOTE_VERSION" ]; then echo "Error: Could not retrieve remote dashboard version from $DASHBOARD_URL." exit 1 fi echo "Latest remote version: $REMOTE_VERSION" # 5. Version comparison if [ "$CURRENT_VERSION" == "$REMOTE_VERSION" ]; then echo "--> Dashboard is already up to date ($CURRENT_VERSION). No action needed." exit 0 fi echo "--> New version detected ($REMOTE_VERSION)! Updating..." # 6. Download and extract rm -rf "$TMP_DIR" mkdir -p "$TMP_DIR/extracted" echo "Downloading $DASHBOARD_URL..." curl -sL "$DASHBOARD_URL" -o "$TMP_DIR/agent.tar.gz" echo "Extracting archive..." tar -xzf "$TMP_DIR/agent.tar.gz" -C "$TMP_DIR/extracted" # Locate the actual root folder containing the 'v3' directory SRC_DIR="$TMP_DIR/extracted" if [ ! -d "$SRC_DIR/v3" ]; then V3_PATH=$(find "$TMP_DIR/extracted" -mindepth 1 -maxdepth 3 -type d -name "v3" -print -quit) if [ -n "$V3_PATH" ]; then SRC_DIR=$(dirname "$V3_PATH") fi fi if [ ! -d "$SRC_DIR/v3" ]; then echo "Error: Could not locate 'v3' directory in extracted archive." rm -rf "$TMP_DIR" exit 1 fi # 7. Create backup BACKUP_DIR="${WEB_DIR}_backup_$(date +%Y%m%d_%H%M%S)" echo "Creating backup in: $BACKUP_DIR" cp -r "$WEB_DIR" "$BACKUP_DIR" # 8. Replace web files echo "Updating web files in $WEB_DIR..." rm -rf "${WEB_DIR:?}"/* cp -r "$SRC_DIR"/* "$WEB_DIR/" # 9. Set permissions if id "netdata" &>/dev/null; then chown -R netdata:netdata "$WEB_DIR" fi # Cleanup rm -rf "$TMP_DIR" echo "=== Successfully updated dashboard to $REMOTE_VERSION ===" echo "Refresh your browser (Ctrl + F5) to use the new dashboard." How It Works Under the Hood The script is engineered with several safeguards to ensure zero downtime issues or broken states: 1. Dynamic Path Resolution: It automatically checks standard web directory paths (`/usr/local/share/netdata/web` vs `/usr/share/netdata/web`) to fit different Linux distributions and installation methods. 2. Prerequisite Validation: It checks for essential command-line tools (`curl`, `tar`, `sed`, `sort`, `tail`, `find`) before doing anything else. 3. Smart Version Parsing: Instead of relying on a manifest API, it inspects file names (`allFiles.*.json`) in both the local directory and the remote `.tar.gz` archive, sorting them properly using `sort -V` (version sorting). If the versions match, it gracefully exits without touching the file system. 4. Automatic Safety Backups: Before making any destructive changes, the script creates a timestamped backup of your current dashboard files (e.g., `/usr/local/share/netdata/web_backup_20261028_214500`). 5. Permissions & Ownership: It automatically detects if the `netdata` system user exists and ensures proper ownership recursively (`chown -R netdata:netdata`). How to Use It Save the script to your server: sudo nano /usr/local/bin/update_netdata_dashboard.sh _(Paste the code above and save the file)_ Make it executable: sudo chmod +x /usr/local/bin/update_netdata_dashboard.sh Run the script: sudo update_netdata_dashboard.sh You can also automate this via Cron if you want your dashboard checked and updated weekly or monthly. Just remember to clear your browser cache (`Ctrl + F5`) after an update to load the latest UI assets cleanly!
ostreff.info
October 28, 2026 at 7:49 PM
Customer no-show problems? Hank turned away paying callers for a 80 booked Saturday, then lost all three jobs and earned /bin/bash. His fix: a 0 booking deposit, credited in full on the day. #SmallBusiness #ContractorTips #ServiceBusiness #GlamourlessSystems
October 26, 2026 at 4:49 PM
Kabi.bi v0.8.7

* External AI providers
* Cute demo with funky CRT skeumorphic terminal
October 25, 2026 at 10:24 PM
I was curious how many Electron apps I had (it turns out: way too many) and whether any auto-updated b/c the emSign/eMudhra thing is a real weakness, especially if you're using DNS not in your control.

All it did was rly make me hate this timeline even more […]

[Original post on mastodon.social]
October 25, 2026 at 1:02 PM
CNN's Dana Bash Gobsmacked By Guest's Abdul El-Sayed Insult

www.mediaite.com/media/tv/cnn...
CNN's Dana Bash Gobsmacked By Guest's Abdul El-Sayed Insult
CNN's Dana Bash was left stunned after a panelist declared that Abdul El-Sayed "sleeps in Osama bin Laden's jersey," setting off a fiery debate.
www.mediaite.com
October 22, 2026 at 1:13 AM
🚨 EUVD-2026-109131
📊 7.1/10
🏢 pypa

📝 virtualenv is a tool for creating isolated virtual python environments. From 21.14.9 until 21.14.13, the bash bin/activate script can copy an attacker-cont...

🔗 https://euvd.enisa.europa.eu/vulnerability/EUVD-2026-109131

#cybersecurity #infosec #cve #euvd
October 23, 2026 at 8:01 PM
Disgusting.

Shame on CNN and Dana Bash for inviting Jason Thielman to come on their air and say, with little push back, that El-Sayed "looks like he's sleeping in bin Laden's jersey."

Fucking despicable.
October 21, 2026 at 4:52 PM
CVE-2026-115586 - virtualenv: Bash activator leaves the --prompt value unescaped in PS1 when promptvars is off, so prompt expansion later executes it (regression in 21.14.9)
CVE ID : CVE-2026-115586

Published : Oct. 23, 2026, 7:34 p.m. | 23 minutes ago

Description : virt...
CVE-2026-115586 - virtualenv: Bash activator leaves the --prompt value unescaped in PS1 when promptvars is off, so prompt expansion later executes it (regression in 21.14.9)
virtualenv is a tool for creating isolated virtual python environments. From 21.14.9 until 21.14.13, the bash bin/activate script can copy an attacker-controlled --prompt value into PS1 without escaping dollar signs or backticks when both promptvars and POSIX mode are disabled during activation. Re-enabling promptvars, running set -o posix, or starting …
cvefeed.io
October 23, 2026 at 8:43 PM
Look at these desperate sons of bitches, talking shit

CNN’s Dana Bash Gobsmacked By Segment’s Explosive Turn After Guest Declares El-Sayed ‘Sleeps in Bin Laden’s Jersey’
October 22, 2026 at 1:19 PM
My first web script was bash running in the cgi-bin directory..

I can not judge...

((Yes, yes it was a visitor counter))
October 21, 2026 at 9:04 AM
If I want "a personal validation machine that never disagrees with you" there's always
#!/bin/bash
echo "Yes, that sounds great!"
October 22, 2026 at 6:08 AM
I'm pretty surprised Apple has not fixed /usr/bin/curl yet— don't run 'curl | bash' in a coffee shop today!

Rather than modify the system certs and trust they won't be modified back, I installed the Homebrew curl and put it first on my #$PATH.
October 20, 2026 at 7:10 PM
CNN’s Dana Bash Gobsmacked By Segment’s Explosive Turn After Guest Declares El-Sayed ‘Sleeps in Bin Laden’s Jersey’
CNN’s Dana Bash Gobsmacked By Segment’s Explosive Turn After Guest Declares El-Sayed ‘Sleeps in Bin Laden’s Jersey’
CNN's Dana Bash was left stunned after a panelist declared that Abdul El-Sayed "sleeps in Osama bin Laden's jersey," setting off a fiery debate. The post CNN’s Dana Bash Gobsmacked By Segment’s Explosive Turn After Guest Declares El-Sayed ‘Sleeps in Bin Laden’s Jersey’ first appeared on Mediaite.
dlvr.it
October 21, 2026 at 7:09 PM
CNN’s Dana Bash Gobsmacked By Segment’s Explosive Turn After Guest Declares El-Sayed ‘Sleeps in Bin Laden’s Jersey’
www.mediaite.com/media/tv/cnn...
CNN's Dana Bash Gobsmacked By Guest's Abdul El-Sayed Insult
CNN's Dana Bash was left stunned after a panelist declared that Abdul El-Sayed "sleeps in Osama bin Laden's jersey," setting off a fiery debate.
www.mediaite.com
October 21, 2026 at 8:42 PM
maybe it's a file corruption (fixable!). if reboot doesn't help, open GRUB on boot, try recovery mode or older kernel if you updated recently. if no joy, try booting from live usb to make sure its not hardware. or look for how to boot without init (it should be smth like init=bin/bash) from GRUB
October 21, 2026 at 10:49 PM