From c3ef5a664fdaa4f770b5d53a20efbc0a2a2996b7 Mon Sep 17 00:00:00 2001 From: Michal Date: Mon, 23 Feb 2026 00:52:31 +0000 Subject: [PATCH] chore: remove accidentally committed logs.sh Co-Authored-By: Claude Opus 4.6 --- .gitignore | 1 + logs.sh | 370 ----------------------------------------------------- 2 files changed, 1 insertion(+), 370 deletions(-) delete mode 100755 logs.sh diff --git a/.gitignore b/.gitignore index 1fbfc64..f114db6 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,4 @@ pgdata/ # Prisma src/db/prisma/migrations/*.sql.backup +logs.sh diff --git a/logs.sh b/logs.sh deleted file mode 100755 index 950e748..0000000 --- a/logs.sh +++ /dev/null @@ -1,370 +0,0 @@ -#!/bin/bash -# Fetch logs and manage containers in the mcpctl Portainer stack -# Usage: ./logs.sh [container_name] [--tail N] [--since TIME] [--follow] -# ./logs.sh restart Restart a container -# ./logs.sh pull Pull an image on the NAS -# ./logs.sh exec Run a command in a container - -set -e - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -PORTAINER_URL="${PORTAINER_URL:-http://10.0.0.194:9000}" -PORTAINER_USER="${PORTAINER_USER:-michal}" -ENDPOINT_ID="2" - -TAIL_LINES=100 -SINCE="" -FOLLOW=false -SHOW_ALL=false -CONTAINER_NAME="" -TIMESTAMPS=true -COMMAND="" -CMD_TARGET="" -EXEC_CMD=() - -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -CYAN='\033[0;36m' -DIM='\033[2m' -NC='\033[0m' - -log_info() { echo -e "${GREEN}[INFO]${NC} $1" >&2; } -log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" >&2; } -log_error() { echo -e "${RED}[ERROR]${NC} $1" >&2; } - -get_password() { - if [[ -n "$PORTAINER_PASSWORD" ]]; then - echo "$PORTAINER_PASSWORD" - return - fi - if [[ -f "$SCRIPT_DIR/.portainer_password" ]]; then - cat "$SCRIPT_DIR/.portainer_password" - return - fi - if [[ -f "$HOME/.portainer_password" ]]; then - cat "$HOME/.portainer_password" - return - fi - read -s -p "Enter Portainer password for $PORTAINER_USER: " password - echo >&2 - echo "$password" -} - -get_jwt_token() { - local password="$1" - local escaped_password - escaped_password=$(printf '%s' "$password" | jq -Rs .) - - local response - response=$(curl -s -X POST "$PORTAINER_URL/api/auth" \ - -H "Content-Type: application/json" \ - -d "{\"Username\":\"$PORTAINER_USER\",\"Password\":$escaped_password}") - - local token - token=$(echo "$response" | jq -r '.jwt // empty') - - if [[ -z "$token" ]]; then - log_error "Authentication failed: $(echo "$response" | jq -r '.message // "Unknown error"')" - exit 1 - fi - echo "$token" -} - -parse_since() { - local since="$1" - local now - now=$(date +%s) - - if [[ "$since" =~ ^([0-9]+)s$ ]]; then - echo $(( now - ${BASH_REMATCH[1]} )) - elif [[ "$since" =~ ^([0-9]+)m$ ]]; then - echo $(( now - ${BASH_REMATCH[1]} * 60 )) - elif [[ "$since" =~ ^([0-9]+)h$ ]]; then - echo $(( now - ${BASH_REMATCH[1]} * 3600 )) - elif [[ "$since" =~ ^([0-9]+)d$ ]]; then - echo $(( now - ${BASH_REMATCH[1]} * 86400 )) - else - date -d "$since" +%s 2>/dev/null || echo "$since" - fi -} - -list_containers() { - local token="$1" - - local containers - containers=$(curl -s -X GET "$PORTAINER_URL/api/endpoints/$ENDPOINT_ID/docker/containers/json?all=true" \ - -H "Authorization: Bearer $token") - - echo "" - printf "${CYAN}%-30s %-15s %-20s %s${NC}\n" "CONTAINER" "STATE" "STATUS" "IMAGE" - printf "${DIM}%-30s %-15s %-20s %s${NC}\n" "─────────" "─────" "──────" "─────" - - echo "$containers" | jq -r '.[] | [ - (.Names[0] // "unnamed" | ltrimstr("/")), - .State, - .Status, - (.Image | split(":")[0] | split("/")[-1]) - ] | @tsv' | sort | while IFS=$'\t' read -r name state status image; do - local color="$NC" - case "$state" in - running) color="$GREEN" ;; - exited|dead) color="$RED" ;; - restarting|paused) color="$YELLOW" ;; - esac - printf "%-30s ${color}%-15s${NC} %-20s %s\n" "$name" "$state" "$status" "$image" - done - - echo "" -} - -resolve_container() { - local token="$1" - local container_name="$2" - - local containers - containers=$(curl -s -X GET "$PORTAINER_URL/api/endpoints/$ENDPOINT_ID/docker/containers/json?all=true" \ - -H "Authorization: Bearer $token") - - local container_id - container_id=$(echo "$containers" | jq -r --arg name "$container_name" \ - '.[] | select(.Names[] | ltrimstr("/") == $name) | .Id') - - if [[ -z "$container_id" ]]; then - container_id=$(echo "$containers" | jq -r --arg name "$container_name" \ - '.[] | select(.Names[] | ltrimstr("/") | contains($name)) | .Id' | head -1) - fi - - if [[ -z "$container_id" ]]; then - log_error "Container '$container_name' not found" - echo "$containers" | jq -r '.[].Names[] | ltrimstr("/")' | sort >&2 - exit 1 - fi - - echo "$container_id" -} - -fetch_logs() { - local token="$1" - local container_name="$2" - - local container_id - container_id=$(resolve_container "$token" "$container_name") - - local query="stderr=true&stdout=true&tail=${TAIL_LINES}" - if [[ "$TIMESTAMPS" == "true" ]]; then - query="${query}×tamps=true" - fi - if [[ -n "$SINCE" ]]; then - local since_ts - since_ts=$(parse_since "$SINCE") - query="${query}&since=${since_ts}" - fi - - if [[ "$FOLLOW" == "true" ]]; then - query="${query}&follow=true" - log_info "Streaming logs for $container_name (Ctrl+C to stop)..." - curl -s -N -X GET "$PORTAINER_URL/api/endpoints/$ENDPOINT_ID/docker/containers/$container_id/logs?${query}" \ - -H "Authorization: Bearer $token" | \ - perl -pe 's/^.{8}//s' - else - curl -s -X GET "$PORTAINER_URL/api/endpoints/$ENDPOINT_ID/docker/containers/$container_id/logs?${query}" \ - -H "Authorization: Bearer $token" | \ - perl -pe 's/^.{8}//s' - fi -} - -fetch_all_logs() { - local token="$1" - - local containers - containers=$(curl -s -X GET "$PORTAINER_URL/api/endpoints/$ENDPOINT_ID/docker/containers/json?all=true" \ - -H "Authorization: Bearer $token") - - local names - names=$(echo "$containers" | jq -r '.[].Names[] | ltrimstr("/")' | sort) - - if [[ "$TAIL_LINES" == "100" ]]; then - TAIL_LINES=50 - fi - - while IFS= read -r name; do - echo "" - echo -e "${CYAN}=== ${name} ===${NC}" - FOLLOW=false fetch_logs "$token" "$name" 2>/dev/null || echo -e "${DIM} (no logs available)${NC}" - done <<< "$names" -} - -restart_container() { - local token="$1" - local container_name="$2" - - local container_id - container_id=$(resolve_container "$token" "$container_name") - - log_info "Restarting $container_name..." - local http_code - http_code=$(curl -s -o /dev/null -w "%{http_code}" -X POST \ - "$PORTAINER_URL/api/endpoints/$ENDPOINT_ID/docker/containers/$container_id/restart" \ - -H "Authorization: Bearer $token") - - if [[ "$http_code" == "204" ]]; then - log_info "$container_name restarted successfully" - else - log_error "Restart failed (HTTP $http_code)" - exit 1 - fi -} - -pull_image() { - local token="$1" - local image="$2" - - local image_name="${image%%:*}" - local tag="${image#*:}" - [[ "$tag" == "$image" ]] && tag="latest" - - log_info "Pulling $image_name:$tag on NAS..." - local response - response=$(curl -s -X POST \ - "$PORTAINER_URL/api/endpoints/$ENDPOINT_ID/docker/images/create?fromImage=$image_name&tag=$tag" \ - -H "Authorization: Bearer $token") - - if echo "$response" | grep -q '"error"'; then - log_error "Pull failed:" - echo "$response" | grep '"error"' - exit 1 - fi - - local status - status=$(echo "$response" | tail -1 | jq -r '.status // empty' 2>/dev/null) - log_info "$status" -} - -exec_container() { - local token="$1" - local container_name="$2" - shift 2 - local cmd=("$@") - - local container_id - container_id=$(resolve_container "$token" "$container_name") - - local cmd_json - cmd_json=$(printf '%s\n' "${cmd[@]}" | jq -R . | jq -s '.') - - local exec_id - exec_id=$(curl -s -X POST \ - "$PORTAINER_URL/api/endpoints/$ENDPOINT_ID/docker/containers/$container_id/exec" \ - -H "Authorization: Bearer $token" \ - -H "Content-Type: application/json" \ - -d "{\"AttachStdout\":true,\"AttachStderr\":true,\"Cmd\":$cmd_json}" | jq -r '.Id') - - if [[ -z "$exec_id" || "$exec_id" == "null" ]]; then - log_error "Failed to create exec instance" - exit 1 - fi - - curl -s -X POST \ - "$PORTAINER_URL/api/endpoints/$ENDPOINT_ID/docker/exec/$exec_id/start" \ - -H "Authorization: Bearer $token" \ - -H "Content-Type: application/json" \ - -d '{"Detach":false,"Tty":true}' -} - -# Parse arguments -while [[ $# -gt 0 ]]; do - case $1 in - --tail|-n) - TAIL_LINES="$2" - shift 2 - ;; - --since) - SINCE="$2" - shift 2 - ;; - --follow|-f) - FOLLOW=true - shift - ;; - --all|-a) - SHOW_ALL=true - shift - ;; - --no-timestamps) - TIMESTAMPS=false - shift - ;; - --help|-h) - echo "Usage: $0 [container_name] [options]" - echo " $0 restart " - echo " $0 pull " - echo " $0 exec " - echo "" - echo "Fetch logs and manage containers in the mcpctl Portainer stack." - echo "" - echo "LOGS:" - echo " (no args) List all containers with status" - echo " Last 100 lines from container" - echo " --all, -a Show logs from all containers" - echo " --tail N, -n N Number of lines (default: 100)" - echo " --since TIME Logs since TIME (e.g., 1h, 30m, 2d)" - echo " --follow, -f Stream logs in real-time" - echo " --no-timestamps Hide timestamps" - echo "" - echo "MANAGEMENT:" - echo " restart Restart a container" - echo " pull Pull an image on the NAS" - echo " exec Run a command in a container" - exit 0 - ;; - restart) - COMMAND="restart" - CMD_TARGET="${2:?Usage: $0 restart }" - shift 2 - ;; - pull) - COMMAND="pull" - CMD_TARGET="${2:?Usage: $0 pull }" - shift 2 - ;; - exec) - COMMAND="exec" - CMD_TARGET="${2:?Usage: $0 exec }" - shift 2 - EXEC_CMD=("$@") - if [[ ${#EXEC_CMD[@]} -eq 0 ]]; then - log_error "Usage: $0 exec " - exit 1 - fi - break - ;; - -*) - log_error "Unknown option: $1" - exit 1 - ;; - *) - CONTAINER_NAME="$1" - shift - ;; - esac -done - -# Main -password=$(get_password) -token=$(get_jwt_token "$password") - -if [[ "$COMMAND" == "restart" ]]; then - restart_container "$token" "$CMD_TARGET" -elif [[ "$COMMAND" == "pull" ]]; then - pull_image "$token" "$CMD_TARGET" -elif [[ "$COMMAND" == "exec" ]]; then - exec_container "$token" "$CMD_TARGET" "${EXEC_CMD[@]}" -elif [[ "$SHOW_ALL" == "true" ]]; then - fetch_all_logs "$token" -elif [[ -n "$CONTAINER_NAME" ]]; then - fetch_logs "$token" "$CONTAINER_NAME" -else - list_containers "$token" -fi