diff --git a/scripts/run/cursor_linux_id_modifier.sh b/scripts/run/cursor_linux_id_modifier.sh index 8ea9dcc..2a62f01 100755 --- a/scripts/run/cursor_linux_id_modifier.sh +++ b/scripts/run/cursor_linux_id_modifier.sh @@ -87,6 +87,33 @@ log_cmd_output() { echo "" >> "$LOG_FILE" } +# sed -i 兼容封装:优先原地编辑;不支持/失败时回退到临时文件替换,提升跨发行版兼容性 +sed_inplace() { + local expr="$1" + local file="$2" + + # GNU sed / BusyBox sed:通常支持 sed -i + if sed -i "$expr" "$file" 2>/dev/null; then + return 0 + fi + + # BSD sed:需要提供 -i '' 形式(少数环境可能出现) + if sed -i '' "$expr" "$file" 2>/dev/null; then + return 0 + fi + + # 最后兜底:临时文件替换(避免不同 sed 的 -i 语义差异) + local temp_file + temp_file=$(mktemp) || return 1 + if sed "$expr" "$file" > "$temp_file"; then + cat "$temp_file" > "$file" + rm -f "$temp_file" + return 0 + fi + rm -f "$temp_file" + return 1 +} + # 获取当前用户 get_current_user() { if [ "$EUID" -eq 0 ]; then @@ -609,12 +636,53 @@ modify_or_add_config() { elif grep -q "}" "$file"; then # key不存在, 在最后一个 '}' 前添加新的key-value对 # 注意:这种方式比较脆弱,如果 JSON 格式不标准或最后一行不是 '}' 会失败 - sed '$ s/}/,\n "'$key'\": "'$value'\"\n}/' "$file" > "$temp_file" || { - log_error "添加配置失败 (注入): $key to $file" - rm -f "$temp_file" - chmod u-w "$file" # 恢复权限 - return 1 - } + # 🔧 兼容修复:不依赖 GNU sed 的 \n 替换扩展;同时避免在 `}` 独占一行时生成无效 JSON + if tail -n 1 "$file" | grep -Eq '^[[:space:]]*}[[:space:]]*$'; then + # 多行 JSON:在最后一个 `}` 前插入新行,并为上一条属性补上逗号 + awk -v key="$key" -v value="$value" ' + { lines[NR] = $0 } + END { + brace = 0 + for (i = NR; i >= 1; i--) { + if (lines[i] ~ /^[[:space:]]*}[[:space:]]*$/) { brace = i; break } + } + if (brace == 0) { exit 2 } + + prev = 0 + for (i = brace - 1; i >= 1; i--) { + if (lines[i] !~ /^[[:space:]]*$/) { prev = i; break } + } + if (prev > 0) { + line = lines[prev] + sub(/[[:space:]]*$/, "", line) + if (line !~ /{$/ && line !~ /,$/) { + lines[prev] = line "," + } else { + lines[prev] = line + } + } + + insert_line = " \"" key "\": \"" value "\"" + for (i = 1; i <= NR; i++) { + if (i == brace) { print insert_line } + print lines[i] + } + } + ' "$file" > "$temp_file" || { + log_error "添加配置失败 (注入): $key to $file" + rm -f "$temp_file" + chmod u-w "$file" # 恢复权限 + return 1 + } + else + # 单行 JSON:直接在末尾 `}` 前插入键值(避免依赖 sed 的 \\n 扩展) + sed "s/}[[:space:]]*$/,\"$key\": \"$value\"}/" "$file" > "$temp_file" || { + log_error "添加配置失败 (注入): $key to $file" + rm -f "$temp_file" + chmod u-w "$file" # 恢复权限 + return 1 + } + fi log_debug "已添加 key '$key' 到文件 '$file' 中" else log_error "无法确定如何添加配置: $key to $file (文件结构可能不标准)" @@ -1116,49 +1184,49 @@ EOF # 如果直接把 someValue.machineId 替换成 "\"<真实值>\"",会形成 ""<真实值>"" 导致 JS 语法错误。 # 因此这里优先替换完整的字符串字面量(包含外层引号),再兜底替换不带引号的占位符。 if grep -q 'someValue\.machineId' "$file"; then - sed -i "s/\"someValue\.machineId\"/\"${machine_id}\"/g" "$file" - sed -i "s/'someValue\.machineId'/\"${machine_id}\"/g" "$file" - sed -i "s/someValue\.machineId/\"${machine_id}\"/g" "$file" + sed_inplace "s/\"someValue\.machineId\"/\"${machine_id}\"/g" "$file" + sed_inplace "s/'someValue\.machineId'/\"${machine_id}\"/g" "$file" + sed_inplace "s/someValue\.machineId/\"${machine_id}\"/g" "$file" log_info " ✓ [方案A] 替换 someValue.machineId" replaced=true fi if grep -q 'someValue\.macMachineId' "$file"; then - sed -i "s/\"someValue\.macMachineId\"/\"${mac_machine_id}\"/g" "$file" - sed -i "s/'someValue\.macMachineId'/\"${mac_machine_id}\"/g" "$file" - sed -i "s/someValue\.macMachineId/\"${mac_machine_id}\"/g" "$file" + sed_inplace "s/\"someValue\.macMachineId\"/\"${mac_machine_id}\"/g" "$file" + sed_inplace "s/'someValue\.macMachineId'/\"${mac_machine_id}\"/g" "$file" + sed_inplace "s/someValue\.macMachineId/\"${mac_machine_id}\"/g" "$file" log_info " ✓ [方案A] 替换 someValue.macMachineId" replaced=true fi if grep -q 'someValue\.devDeviceId' "$file"; then - sed -i "s/\"someValue\.devDeviceId\"/\"${device_id}\"/g" "$file" - sed -i "s/'someValue\.devDeviceId'/\"${device_id}\"/g" "$file" - sed -i "s/someValue\.devDeviceId/\"${device_id}\"/g" "$file" + sed_inplace "s/\"someValue\.devDeviceId\"/\"${device_id}\"/g" "$file" + sed_inplace "s/'someValue\.devDeviceId'/\"${device_id}\"/g" "$file" + sed_inplace "s/someValue\.devDeviceId/\"${device_id}\"/g" "$file" log_info " ✓ [方案A] 替换 someValue.devDeviceId" replaced=true fi if grep -q 'someValue\.sqmId' "$file"; then - sed -i "s/\"someValue\.sqmId\"/\"${sqm_id}\"/g" "$file" - sed -i "s/'someValue\.sqmId'/\"${sqm_id}\"/g" "$file" - sed -i "s/someValue\.sqmId/\"${sqm_id}\"/g" "$file" + sed_inplace "s/\"someValue\.sqmId\"/\"${sqm_id}\"/g" "$file" + sed_inplace "s/'someValue\.sqmId'/\"${sqm_id}\"/g" "$file" + sed_inplace "s/someValue\.sqmId/\"${sqm_id}\"/g" "$file" log_info " ✓ [方案A] 替换 someValue.sqmId" replaced=true fi if grep -q 'someValue\.sessionId' "$file"; then - sed -i "s/\"someValue\.sessionId\"/\"${session_id}\"/g" "$file" - sed -i "s/'someValue\.sessionId'/\"${session_id}\"/g" "$file" - sed -i "s/someValue\.sessionId/\"${session_id}\"/g" "$file" + sed_inplace "s/\"someValue\.sessionId\"/\"${session_id}\"/g" "$file" + sed_inplace "s/'someValue\.sessionId'/\"${session_id}\"/g" "$file" + sed_inplace "s/someValue\.sessionId/\"${session_id}\"/g" "$file" log_info " ✓ [方案A] 替换 someValue.sessionId" replaced=true fi if grep -q 'someValue\.firstSessionDate' "$file"; then - sed -i "s/\"someValue\.firstSessionDate\"/\"${first_session_date}\"/g" "$file" - sed -i "s/'someValue\.firstSessionDate'/\"${first_session_date}\"/g" "$file" - sed -i "s/someValue\.firstSessionDate/\"${first_session_date}\"/g" "$file" + sed_inplace "s/\"someValue\.firstSessionDate\"/\"${first_session_date}\"/g" "$file" + sed_inplace "s/'someValue\.firstSessionDate'/\"${first_session_date}\"/g" "$file" + sed_inplace "s/someValue\.firstSessionDate/\"${first_session_date}\"/g" "$file" log_info " ✓ [方案A] 替换 someValue.firstSessionDate" replaced=true fi @@ -1481,25 +1549,19 @@ disable_auto_update() { # 备份 cp "$config" "${config}.bak_$(date +%Y%m%d%H%M%S)" 2>/dev/null - # 尝试修改 JSON (如果存在且是 settings.json) - if [[ "$config" == *settings.json ]]; then - # 尝试添加或修改 "update.mode": "none" - if grep -q '"update.mode"' "$config"; then - sed -i 's/"update.mode":[[:space:]]*"[^"]*"/"update.mode": "none"/' "$config" || log_warn "修改 settings.json 中的 update.mode 失败" - elif grep -q "}" "$config"; then # 尝试注入 - sed -i '$ s/}/,\n "update.mode": "none"\n}/' "$config" || log_warn "注入 update.mode 到 settings.json 失败" + # 尝试修改 JSON (如果存在且是 settings.json) + if [[ "$config" == *settings.json ]]; then + # 🔧 兼容修复:复用 modify_or_add_config 统一处理替换/注入,避免 sed -i 与 \n 扩展差异 + if modify_or_add_config "update.mode" "none" "$config"; then + ((disabled_count++)) + log_info "已尝试在 '$config' 中设置 'update.mode' 为 'none'" else - log_warn "无法修改 settings.json 以禁用更新(结构未知)" + log_warn "修改 settings.json 中的 update.mode 失败: $config" fi - # 确保权限正确 + elif [[ "$config" == *update-config.json ]]; then + # 直接覆盖 update-config.json + echo '{"autoCheck": false, "autoDownload": false}' > "$config" chown "$CURRENT_USER":"$(id -g -n "$CURRENT_USER")" "$config" || log_warn "设置所有权失败: $config" - chmod 644 "$config" || log_warn "设置权限失败: $config" - ((disabled_count++)) - log_info "已尝试在 '$config' 中设置 'update.mode' 为 'none'" - elif [[ "$config" == *update-config.json ]]; then - # 直接覆盖 update-config.json - echo '{"autoCheck": false, "autoDownload": false}' > "$config" - chown "$CURRENT_USER":"$(id -g -n "$CURRENT_USER")" "$config" || log_warn "设置所有权失败: $config" chmod 644 "$config" || log_warn "设置权限失败: $config" ((disabled_count++)) log_info "已覆盖更新配置文件: $config" diff --git a/scripts/run/cursor_mac_id_modifier.sh b/scripts/run/cursor_mac_id_modifier.sh index 923c8de..ff45470 100644 --- a/scripts/run/cursor_mac_id_modifier.sh +++ b/scripts/run/cursor_mac_id_modifier.sh @@ -260,7 +260,8 @@ test_cursor_environment() { issues+=("配置文件不存在: $config_path") else # 验证JSON格式 - if python3 -c "import json; json.load(open('$config_path'))" 2>/dev/null; then + # 🔧 修复:避免把路径直接拼进 Python 源码字符串(路径包含引号等特殊字符时会导致语法错误) + if python3 -c 'import json, sys; json.load(open(sys.argv[1], "r", encoding="utf-8"))' "$config_path" 2>/dev/null; then log_info "✅ [检查] 配置文件格式正确" else issues+=("配置文件格式错误或损坏") @@ -449,7 +450,8 @@ modify_machine_code_config() { # 验证配置文件格式并显示结构 log_info "🔍 [验证] 检查配置文件格式..." - if ! python3 -c "import json; json.load(open('$config_path'))" 2>/dev/null; then + # 🔧 修复:避免把路径直接拼进 Python 源码字符串(路径包含引号等特殊字符时会导致语法错误) + if ! python3 -c 'import json, sys; json.load(open(sys.argv[1], "r", encoding="utf-8"))' "$config_path" 2>/dev/null; then log_error "❌ [错误] 配置文件格式错误或损坏" log_info "💡 [建议] 配置文件可能已损坏,建议选择'重置环境+修改机器码'选项" return 1 @@ -458,23 +460,26 @@ modify_machine_code_config() { # 显示当前配置文件中的相关属性 log_info "📋 [当前配置] 检查现有的遥测属性:" + # 🔧 修复:避免把路径直接拼进 Python 源码字符串(路径包含引号等特殊字符时会导致语法错误) python3 -c " -import json -try: - with open('$config_path', 'r', encoding='utf-8') as f: - config = json.load(f) - - properties = ['telemetry.machineId', 'telemetry.macMachineId', 'telemetry.devDeviceId', 'telemetry.sqmId'] - for prop in properties: - if prop in config: - value = config[prop] - display_value = value[:20] + '...' if len(value) > 20 else value - print(f' ✓ {prop} = {display_value}') - else: - print(f' - {prop} (不存在,将创建)') -except Exception as e: - print(f'Error reading config: {e}') -" + import json + import sys + try: + config_path = sys.argv[1] + with open(config_path, 'r', encoding='utf-8') as f: + config = json.load(f) + + properties = ['telemetry.machineId', 'telemetry.macMachineId', 'telemetry.devDeviceId', 'telemetry.sqmId'] + for prop in properties: + if prop in config: + value = config[prop] + display_value = value[:20] + '...' if len(value) > 20 else value + print(f' ✓ {prop} = {display_value}') + else: + print(f' - {prop} (不存在,将创建)') + except Exception as e: + print(f'Error reading config: {e}') + " "$config_path" echo # 显示操作进度 @@ -535,40 +540,49 @@ except Exception as e: log_info "⏳ [进度] 4/5 - 更新配置文件..." # 使用Python修改JSON配置(更可靠,安全方式) + # 🔧 修复:避免把路径/值直接拼进 Python 源码字符串(引号/反斜杠等特殊字符会导致语法错误或写入错误) local python_result=$(python3 -c " -import json -import sys - -try: - with open('$config_path', 'r', encoding='utf-8') as f: - config = json.load(f) - - # 安全更新配置,确保属性存在 - # 🔧 修复: 添加 storage.serviceMachineId 和 telemetry.firstSessionDate - properties_to_update = { - 'telemetry.machineId': '$MACHINE_ID', - 'telemetry.macMachineId': '$MAC_MACHINE_ID', - 'telemetry.devDeviceId': '$UUID', - 'telemetry.sqmId': '$SQM_ID', - 'storage.serviceMachineId': '$SERVICE_MACHINE_ID', - 'telemetry.firstSessionDate': '$FIRST_SESSION_DATE' - } - - for key, value in properties_to_update.items(): - if key in config: - print(f' ✓ 更新属性: {key}') - else: - print(f' + 添加属性: {key}') - config[key] = value - - with open('$config_path', 'w', encoding='utf-8') as f: - json.dump(config, f, indent=2, ensure_ascii=False) - - print('SUCCESS') -except Exception as e: - print(f'ERROR: {e}') - sys.exit(1) -" 2>&1) + import json + import sys + + try: + config_path = sys.argv[1] + machine_id = sys.argv[2] + mac_machine_id = sys.argv[3] + dev_device_id = sys.argv[4] + sqm_id = sys.argv[5] + service_machine_id = sys.argv[6] + first_session_date = sys.argv[7] + + with open(config_path, 'r', encoding='utf-8') as f: + config = json.load(f) + + # 安全更新配置,确保属性存在 + # 🔧 修复: 添加 storage.serviceMachineId 和 telemetry.firstSessionDate + properties_to_update = { + 'telemetry.machineId': machine_id, + 'telemetry.macMachineId': mac_machine_id, + 'telemetry.devDeviceId': dev_device_id, + 'telemetry.sqmId': sqm_id, + 'storage.serviceMachineId': service_machine_id, + 'telemetry.firstSessionDate': first_session_date + } + + for key, value in properties_to_update.items(): + if key in config: + print(f' ✓ 更新属性: {key}') + else: + print(f' + 添加属性: {key}') + config[key] = value + + with open(config_path, 'w', encoding='utf-8') as f: + json.dump(config, f, indent=2, ensure_ascii=False) + + print('SUCCESS') + except Exception as e: + print(f'ERROR: {e}') + sys.exit(1) + " "$config_path" "$MACHINE_ID" "$MAC_MACHINE_ID" "$UUID" "$SQM_ID" "$SERVICE_MACHINE_ID" "$FIRST_SESSION_DATE" 2>&1) # 🔧 关键修复:正确解析Python执行结果 local python_exit_code=$? @@ -598,38 +612,48 @@ except Exception as e: chmod 644 "$config_path" 2>/dev/null || true # 验证修改是否成功 + # 🔧 修复:避免把路径/值直接拼进 Python 源码字符串(引号/反斜杠等特殊字符会导致语法错误或写入错误) local verification_result=$(python3 -c " -import json -try: - with open('$config_path', 'r', encoding='utf-8') as f: - config = json.load(f) - - # 🔧 修复: 添加 storage.serviceMachineId 和 telemetry.firstSessionDate 验证 - properties_to_check = { - 'telemetry.machineId': '$MACHINE_ID', - 'telemetry.macMachineId': '$MAC_MACHINE_ID', - 'telemetry.devDeviceId': '$UUID', - 'telemetry.sqmId': '$SQM_ID', - 'storage.serviceMachineId': '$SERVICE_MACHINE_ID', - 'telemetry.firstSessionDate': '$FIRST_SESSION_DATE' - } - - verification_passed = True - for key, expected_value in properties_to_check.items(): - actual_value = config.get(key) - if actual_value == expected_value: - print(f'✓ {key}: 验证通过') - else: - print(f'✗ {key}: 验证失败 (期望: {expected_value}, 实际: {actual_value})') - verification_passed = False - - if verification_passed: - print('VERIFICATION_SUCCESS') - else: - print('VERIFICATION_FAILED') -except Exception as e: - print(f'VERIFICATION_ERROR: {e}') -" 2>&1) + import json + import sys + try: + config_path = sys.argv[1] + machine_id = sys.argv[2] + mac_machine_id = sys.argv[3] + dev_device_id = sys.argv[4] + sqm_id = sys.argv[5] + service_machine_id = sys.argv[6] + first_session_date = sys.argv[7] + + with open(config_path, 'r', encoding='utf-8') as f: + config = json.load(f) + + # 🔧 修复: 添加 storage.serviceMachineId 和 telemetry.firstSessionDate 验证 + properties_to_check = { + 'telemetry.machineId': machine_id, + 'telemetry.macMachineId': mac_machine_id, + 'telemetry.devDeviceId': dev_device_id, + 'telemetry.sqmId': sqm_id, + 'storage.serviceMachineId': service_machine_id, + 'telemetry.firstSessionDate': first_session_date + } + + verification_passed = True + for key, expected_value in properties_to_check.items(): + actual_value = config.get(key) + if actual_value == expected_value: + print(f'✓ {key}: 验证通过') + else: + print(f'✗ {key}: 验证失败 (期望: {expected_value}, 实际: {actual_value})') + verification_passed = False + + if verification_passed: + print('VERIFICATION_SUCCESS') + else: + print('VERIFICATION_FAILED') + except Exception as e: + print(f'VERIFICATION_ERROR: {e}') + " "$config_path" "$MACHINE_ID" "$MAC_MACHINE_ID" "$UUID" "$SQM_ID" "$SERVICE_MACHINE_ID" "$FIRST_SESSION_DATE" 2>&1) # 检查验证结果(忽略其他输出,只关注最终结果) if echo "$verification_result" | grep -q "VERIFICATION_SUCCESS"; then