wordpressbashubuntuscriptingubuntu-server

Problem while trying to replace some lines using sed


I was trying to create a script that installs Wordpress automatically in Ubuntu Server, for a college project. The problem comes when I try to insert the authentication keys inside of the wp-config.php file. The keys are obtained through an url that generates them, and can be obtained using curl. The output of the command: curl -s https://api.wordpress.org/secret-key/1.1/salt/ is something like this:

define('AUTH_KEY',         '$+ef);AyI`T!+<2gPHrG%R^&6NX`E~+TumT qdMWY&QP.l) TYz2fENG}[bCc8~:');
define('SECURE_AUTH_KEY',  'omDNxow|,(WIuk-pS MRG&P&2Shlk8Y=Q<PH|+fA;T`~b:?I- <Q|ng}~TX|@=^s');
define('LOGGED_IN_KEY',    '3d[bU]VTc+R84#+~TYAO#?c+FQLWVxDq&1wGUZC;$d@n1)9We VXrGIJN3cX*d%E');
define('NONCE_KEY',        'S(No,u/>6(Q4!2(u6ri-LRAp8uESFY{__ZWbH(nP]YOC3WA@JvWkkwrIY<^Dvm b');
define('AUTH_SALT',        'ph512NCyJ?3]g|a|<5@fH5cCX&Rw{%+}Sm?gmVQ6WRnj-]N2]rg+i{21<-05`H>o');
define('SECURE_AUTH_SALT', 'hig|pYFPmF6w1Jm&R:U{ZDvxkeOW*#63ys!b7]FT|v*Crm>8kK!;hw=`hovm)Rqp');
define('LOGGED_IN_SALT',   'S[40r?y~.*-]Z9]0qLEOTp}}+T|lO|p-Qz|^h}:C{s&_X]kOkPp+uKuOhy3j`sf9');
define('NONCE_SALT',       'Ph|CZMq3C]<p2*G=qV2PSj5o4mYjTg!NX`[G---_W%w2H:`e6Q@1!a:]vYWxQlP#');

And the default values look like this: define( 'AUTH_KEY', 'put your unique phrase here' );

I want to insert the keys in the same lines where the sample lines are. If I just append the output of curl to the document, it won't work. The problem is that the keys are formed by a lot of conflictive characters, which cause errors when I try to replace the lines using sed. The bash script I have done to replace the lines doesn't work because of the conflictive characters. This is the script:

key_names=("AUTH_KEY SECURE_AUTH_KEY LOGGED_IN_KEY NONCE_KEY AUTH_SALT SECURE_AUTH_SALT LOGGED_IN_SALT NONCE_SALT")
key_values=($(curl -s https://api.wordpress.org/secret-key/1.1/salt/ | awk -F"'" '{for(i=2;i<=NF;i+=2) print $i}' | awk 'length >30'))

# iterate over each element to insert the keys in wp-config.php proper line
for ((i=0; i<${#key_values[@]}; i++)); do
    sed -i "s/define( '${key_names[i]}', '.*' );/define( '${key_names[i]}', '${key_values[i]}' );/" $WP_CONF_FILE
done

I tried by just redirecting the output of the curl command to the file, but it doesn't work, the lines need to be inserted where the example lines are. I also tried to replace the lines with sed (using the script above), but it doesn't work because of the conflictive characters. I also tried asking ChatGPT, but it didn't really come up with any solution.

Any idea of how could I solve this? Thank you!


Solution

  • sed usually isn't the best choice for substitutions using input values since it doesn't understand literal strings, see Is it possible to escape regex metacharacters reliably with sed for details. Also using a shell loop is very slow, as is running sed multiple times on your input file, and it introduces rainy day cases where a subsequent substitution might replace a change made by an earlier substitution.

    I think this might be what you're trying to do, using any awk and just modifying the input file once for all keys together:

    $ cat tst.sh
    #!/usr/bin/env bash
    
    tmp=$(mktemp) || exit 1
    trap 'rm -f "$tmp"; exit' EXIT
    
    curl -k -s 'https://api.wordpress.org/secret-key/1.1/salt/' |
    awk -F"'" '
        BEGIN { OFS=FS }
        NR == FNR {
            map[$2] = $4
            next
        }
        /^define\(/ && ($2 in map) {
            $4 = map[$2]
        }
        { print }
    ' - "$WP_CONF_FILE" > "$tmp" &&
    mv -- "$tmp" "$WP_CONF_FILE"
    

    When I ran your curl command from the command-line I got the same kind of output you show but when I ran it from a script I got no output so when I removed the -s option to see if it was reporting any failures I get curl: (35) schannel: next InitializeSecurityContext failed: Unknown error (0x80092012) - The revocation function was unable to check revocation for the certificate.. I had to add -k to skip certificate validation to get it to work from a script.

    Copying an example file google found on github to use as sample input:

    $ curl -k -s 'https://raw.githubusercontent.com/WordPress/WordPress/master/wp-config-sample.php' > wp-config-sample.php
    $ cat wp-config-sample.php
    <?php
    /**
     * The base configuration for WordPress
     *
     * The wp-config.php creation script uses this file during the installation.
     * You don't have to use the web site, you can copy this file to "wp-config.php"
     * and fill in the values.
     *
     * This file contains the following configurations:
     *
     * * Database settings
     * * Secret keys
     * * Database table prefix
     * * ABSPATH
     *
     * @link https://wordpress.org/documentation/article/editing-wp-config-php/
     *
     * @package WordPress
     */
    
    // ** Database settings - You can get this info from your web host ** //
    /** The name of the database for WordPress */
    define( 'DB_NAME', 'database_name_here' );
    
    /** Database username */
    define( 'DB_USER', 'username_here' );
    
    /** Database password */
    define( 'DB_PASSWORD', 'password_here' );
    
    /** Database hostname */
    define( 'DB_HOST', 'localhost' );
    
    /** Database charset to use in creating database tables. */
    define( 'DB_CHARSET', 'utf8' );
    
    /** The database collate type. Don't change this if in doubt. */
    define( 'DB_COLLATE', '' );
    
    /**#@+
     * Authentication unique keys and salts.
     *
     * Change these to different unique phrases! You can generate these using
     * the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}.
     *
     * You can change these at any point in time to invalidate all existing cookies.
     * This will force all users to have to log in again.
     *
     * @since 2.6.0
     */
    define( 'AUTH_KEY',         'put your unique phrase here' );
    define( 'SECURE_AUTH_KEY',  'put your unique phrase here' );
    define( 'LOGGED_IN_KEY',    'put your unique phrase here' );
    define( 'NONCE_KEY',        'put your unique phrase here' );
    define( 'AUTH_SALT',        'put your unique phrase here' );
    define( 'SECURE_AUTH_SALT', 'put your unique phrase here' );
    define( 'LOGGED_IN_SALT',   'put your unique phrase here' );
    define( 'NONCE_SALT',       'put your unique phrase here' );
    
    /**#@-*/
    
    /**
     * WordPress database table prefix.
     *
     * You can have multiple installations in one database if you give each
     * a unique prefix. Only numbers, letters, and underscores please!
     */
    $table_prefix = 'wp_';
    
    /**
     * For developers: WordPress debugging mode.
     *
     * Change this to true to enable the display of notices during development.
     * It is strongly recommended that plugin and theme developers use WP_DEBUG
     * in their development environments.
     *
     * For information on other constants that can be used for debugging,
     * visit the documentation.
     *
     * @link https://wordpress.org/documentation/article/debugging-in-wordpress/
     */
    define( 'WP_DEBUG', false );
    
    /* Add any custom values between this line and the "stop editing" line. */
    
    
    
    /* That's all, stop editing! Happy publishing. */
    
    /** Absolute path to the WordPress directory. */
    if ( ! defined( 'ABSPATH' ) ) {
            define( 'ABSPATH', __DIR__ . '/' );
    }
    
    /** Sets up WordPress vars and included files. */
    require_once ABSPATH . 'wp-settings.php';
    

    I tested my script using:

    $ cp wp-config-sample.php orig
    $ WP_CONF_FILE='wp-config-sample.php' ./tst.sh
    $ diff orig wp-config-sample.php
    51,58c51,58
    < define( 'AUTH_KEY',         'put your unique phrase here' );
    < define( 'SECURE_AUTH_KEY',  'put your unique phrase here' );
    < define( 'LOGGED_IN_KEY',    'put your unique phrase here' );
    < define( 'NONCE_KEY',        'put your unique phrase here' );
    < define( 'AUTH_SALT',        'put your unique phrase here' );
    < define( 'SECURE_AUTH_SALT', 'put your unique phrase here' );
    < define( 'LOGGED_IN_SALT',   'put your unique phrase here' );
    < define( 'NONCE_SALT',       'put your unique phrase here' );
    ---
    > define( 'AUTH_KEY',         '6O 0_j!ReXNj`Uf5#Q+}CB@db6HA(I~+u`i,fiyIYSp|Rj{!p>oytFo}8Sx8!Fm^' );
    > define( 'SECURE_AUTH_KEY',  'l)Z3t=c1TXI7N)[zV6?i:l`,MjG?Q]a~Wvp,+P+9|w;hxi1Rkc1)`~/mUA1S>Tb{' );
    > define( 'LOGGED_IN_KEY',    'hgnD89/M7:GrSd|%0U.}26k)a;S:-xFW_iQA0ppNm-J_8=:hKjoM>Q&XT^&!|lbl' );
    > define( 'NONCE_KEY',        ')X, Tk%(uihbq[caL}dvR{Tt55D!:m+ePK`4h(|li~mcE8Mg._gXxgo)++&N6Lb+' );
    > define( 'AUTH_SALT',        'lF?JrQUDFfVZo.HHGa^m=-;?Q#c2ViC!sfNvyu[[6+0vl4jo41w-q+%!~hrm`>D~' );
    > define( 'SECURE_AUTH_SALT', '2cWJ5Z{j[(QZ:h/M_0@&f>;F`q)y1A@z; Y%Ra^Vf;R}Yvtd7.CftK-BzO|+!S ~' );
    > define( 'LOGGED_IN_SALT',   ':jt]g7smA2Bw,|Caf|RJ4=Y)g|-c/afF-X W7),.8WRm|<n=rorm):~i!A^]VwJD' );
    > define( 'NONCE_SALT',       'SrW-S`ylE0Onco3A*rMp7;JQ}Pap}P_*|E+pDt>3p:Yz-r6*8RktYQYAMLh}nuL*' );
    

    By the way, in your original script there was no need to hard-code an array key_names[] when you could've just read the names from the curl output like you're reading the values, e.g. with 2 indexed arrays as you have:

    while IFS="'" read -r _ name _ value _; do
        key_names+=( "$name" )
        key_values+=( "$value" )
    done < <(curl -k -s 'https://api.wordpress.org/secret-key/1.1/salt/')
    

    or a single associative array:

    declare -A key_names2values
    while IFS="'" read -r _ name _ value _; do
        key_names2values["$name"]="$value"
    done < <(curl -k -s 'https://api.wordpress.org/secret-key/1.1/salt/')
    

    Also | awk -F"'" '{for(i=2;i<=NF;i+=2) print $i}' | awk 'length >30') could've just been | awk -F"'" '{print $4}' or even | curl -d"'" -f4.